Portfolio optimization is an important topic in Finance. Modern portfolio theory (MPT) states that investors are risk averse and given a level of risk, they will choose the portfolios that offer the most return. To do that we need to optimize the portfolios.

To perform the optimization we will need

So lets begin

Downloading data

First lets load our packages

# list.of.packages <- c('tidyverse','tidyquant', 'plotly','timetk','GA','xtable', 'textreadr','rvest','fGarch',"dplyr", "dygraphs", "quantmod", "TTR", 'zoo', 'tseries', 'fGarch','PEIP','tidyverse','gridExtra', 'gdata', 'xtable',"dygraphs") 
# new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
# if(length(new.packages) > 0) {install.packages(new.packages)}
# lapply(list.of.packages, require, character.only=T)

library('tidyverse')
library('tidyquant')
## Warning: package 'xts' was built under R version 4.3.3
## Warning: package 'quantmod' was built under R version 4.3.2
library('plotly')
library('timetk')
library('GA')
## Warning: package 'GA' was built under R version 4.3.2
library('xtable')
#library('textreadr')
library('rvest')
library('fGarch')
library("dplyr")
library("dygraphs")
library("quantmod")
library("TTR")
library('zoo')
library('tseries')
library('fGarch')
library('PEIP')
library('tidyverse')
library('gridExtra')
library('gdata')
library('xtable')
library("dygraphs")
# Load all the required functions needed get the results
## function to generate weight
# get_weights <- function(N){
#  return(diff(c(0, sort(runif(N-1, min = 0, max = 1)), 1)))
# }
get_weights <- function(N){
  w<- runif(N, min = 0, max = 1)
  return(w/sum(w))
}
# skewness correlation
skewrho <- function(X){
  skewrho.cor <- cor(X-mean(X), (X-mean(X))^2)
  return(skewrho.cor)
}

# sign correlation
rho.cal<-function(X){
  rho.hat<-cor(sign(X-mean(X)), X-mean(X))
  return(rho.hat)
}

# volatlity correlation
rho.vol<-function(X){
  rho.vol<-cor(abs(X-mean(X)), (X-mean(X))^2)
  return(rho.vol)
}

Simulation study for sign correlation and volatility correlation

# simulate normal, t(2), t(3), t(4), t(5)
sample <- 8000
sim.n <- rnorm (sample)     # sign correlation of a normal distribution is sqrt(2/pi)=0.7979
sim.t25 <- rt (sample, df = 2.5)
sim.t3 <- rt (sample, df = 3)
sim.t35 <- rt (sample, df = 3.5)
sim.t4 <- rt (sample, df = 4)
sim.t5 <- rt (sample, df = 5)
data <- cbind (sim.t25, sim.t3, sim.t35, sim.t4, sim.t5, sim.n)

skewrho<-apply(as.matrix(data), MARGIN=2, FUN=skewrho)
rhosign<-apply(as.matrix(data), MARGIN=2, FUN=rho.cal)
rhovol<-apply(as.matrix(data), MARGIN=2, FUN=rho.vol)

assetsummary<-data.frame(apply(data, 2, mean), apply(data, 2, sd), apply(data, 2, skewness), apply(data, 2, kurtosis), skewrho, rhovol, rhosign)
xtable(assetsummary, digits=4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:57:31 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrr}
##   \hline
##  & apply.data..2..mean. & apply.data..2..sd. & apply.data..2..skewness. & apply.data..2..kurtosis. & skewrho & rhovol & rhosign \\ 
##   \hline
## sim.t25 & 0.0155 & 2.0349 & 1.2364 & 37.1101 & 0.1977 & 0.7734 & 0.5995 \\ 
##   sim.t3 & 0.0115 & 1.8545 & 3.0421 & 117.8691 & 0.2779 & 0.7114 & 0.6042 \\ 
##   sim.t35 & 0.0020 & 1.4730 & -0.1618 & 5.8054 & -0.0579 & 0.8503 & 0.7078 \\ 
##   sim.t4 & -0.0044 & 1.4740 & 0.0379 & 22.1002 & 0.0077 & 0.7415 & 0.6870 \\ 
##   sim.t5 & -0.0189 & 1.2836 & -0.2324 & 3.5381 & -0.0988 & 0.8541 & 0.7366 \\ 
##   sim.n & 0.0166 & 1.0099 & 0.0121 & -0.0263 & 0.0086 & 0.9360 & 0.7991 \\ 
##    \hline
## \end{tabular}
## \end{table}

Next lets select a few stocks to build our portfolios.

We will choose some stocks.

Lets download the price data.

Portfolio selected from emperical_DBSCAN_2023_lowest_average_clustering

#Import data

emperical_DBSCAN_2023_lowest_average_clustering <- read.csv("~/Desktop/PO/DBSCAN/EMP/2023/emperical_DBSCAN_2023_lowest_average_clustering.csv")

#remove the date column
asset_prices<-emperical_DBSCAN_2023_lowest_average_clustering[,-1]
# calculate returns
ret_tidy1 = apply(asset_prices,2, log)
head(ret_tidy1)
##       ETH.USD      JNJ      MMM        T        V
## [1,] 7.102317 5.129780 4.541414 2.818319 5.320976
## [2,] 7.136107 5.140609 4.563061 2.839439 5.345835
## [3,] 7.131250 5.133198 4.545407 2.843089 5.338754
## [4,] 7.146283 5.141275 4.575528 2.859610 5.369723
## [5,] 7.186552 5.115025 4.576080 2.848537 5.373619
## [6,] 7.197874 5.112630 4.586594 2.870870 5.384945
ret_tidy2 = diff(ret_tidy1)
head(ret_tidy2)
##           ETH.USD          JNJ           MMM            T            V
## [1,]  0.033789247  0.010828468  0.0216469352  0.021120151  0.024858315
## [2,] -0.004856888 -0.007410884 -0.0176539006  0.003650439 -0.007080053
## [3,]  0.015033458  0.008076773  0.0301208147  0.016520824  0.030968202
## [4,]  0.040269095 -0.026249972  0.0005522516 -0.011072737  0.003895977
## [5,]  0.011321725 -0.002394897  0.0105132859  0.022332525  0.011326329
## [6,]  0.037696756 -0.001599760  0.0076967369 -0.003086252  0.004557899
ret_tidy = exp (ret_tidy2) - 1 #simple returns
#remove first row
asset_returns <- ret_tidy[-1,]

#no.of assets in the portfolio 
nasset<-ncol(asset_returns)

# testing and training data sets (each data set has 252 observations)
# Divide the data set in to 3:1 (75% training and 25% testing)
# testing period - January - September (189 data points)
# training period - October - December (62 data points)

n.total<-252
n.train<- 189

train = asset_returns[1:n.train,]
test = asset_returns[-(1:(n.train)),]
##summary statistics 
rhosign<-apply(as.matrix(train), MARGIN=2, FUN=rho.cal)
rhovol<-apply(as.matrix(train), MARGIN=2, FUN=rho.vol)
assetsummary<-data.frame(apply(train, 2, mean), apply(train, 2, sd), rhovol, rhosign, apply(train, 2, skewness),
                 apply(train, 2, kurtosis))
xtable(assetsummary, digits=4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:57:31 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrr}
##   \hline
##  & apply.train..2..mean. & apply.train..2..sd. & rhovol & rhosign & apply.train..2..skewness. & apply.train..2..kurtosis. \\ 
##   \hline
## ETH.USD & 0.0018 & 0.0303 & 0.8551 & 0.7043 & 0.9948 & 5.3989 \\ 
##   JNJ & -0.0005 & 0.0108 & 0.8876 & 0.6752 & 0.7182 & 7.3649 \\ 
##   MMM & -0.0015 & 0.0178 & 0.8954 & 0.7041 & 0.5870 & 4.1278 \\ 
##   T & -0.0010 & 0.0174 & 0.9085 & 0.6455 & -0.5911 & 10.3598 \\ 
##   V & 0.0006 & 0.0101 & 0.9360 & 0.7797 & 0.2072 & 0.6578 \\ 
##    \hline
## \end{tabular}
## \end{table}
plot(train, legend.loc=1)
## Warning in plot.window(...): "legend.loc" is not a graphical parameter
## Warning in plot.xy(xy, type, ...): "legend.loc" is not a graphical parameter
## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter

## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter
## Warning in box(...): "legend.loc" is not a graphical parameter
## Warning in title(...): "legend.loc" is not a graphical parameter

Lets calculate annualized portfolio return, risk, and gamma from the simulated portfolio returns with portfolio weights. (simulated weights)

## portfolio return, sd and gamma
## w is the random weight
## data = train or test
portfolio_info = function(w, data){
  port.data <- data%*%as.vector(w)
  port.cdf <- ecdf(port.data)
  port.return <- mean (port.data)
  port.sd <- sd (port.data)
  port.signrho <- cor (port.data - port.return, sign(port.data - port.return))
# port.signrho3 <- cor (sign(port.data - port.return), (port.data - port.return)^3)
# port.skewrho <- cor (port.data - port.return, (port.data - port.return)^2)
  port.volcor <- cor (abs(port.data - port.return), (port.data - port.return)^2) #volatlity correlation
  port.skewness <- skewness (port.data) #mu_3/sigma^3
  port.kurtosis <- kurtosis (port.data) #excess kurtosis mu_4/sigma^4 - 3
  return(c(port.return, port.sd, port.volcor, port.signrho, port.cdf(port.return), port.skewness, port.kurtosis))
}
# In stat matrix and weight matrix nrow = no.of assets in the portfolio (need to change), ncol is fixed to 7 , for loop i in 1:nrow
stat<-matrix(0, nrow = nasset, ncol = 7)
weight<-matrix(0, nrow = nasset, ncol = nasset)
for (i in 1:nasset){
weight[i, ] <- get_weights(nasset)
stat[i, ] <- portfolio_info (weight[i, ], as.matrix(train))
}
xtable(weight, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:57:31 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.1227 & 0.3656 & 0.1432 & 0.2863 & 0.0822 \\ 
##   2 & 0.4839 & 0.1191 & 0.2415 & 0.1281 & 0.0274 \\ 
##   3 & 0.1865 & 0.1096 & 0.2091 & 0.0185 & 0.4763 \\ 
##   4 & 0.1952 & 0.2797 & 0.2921 & 0.0568 & 0.1763 \\ 
##   5 & 0.3635 & 0.1833 & 0.3048 & 0.1447 & 0.0037 \\ 
##    \hline
## \end{tabular}
## \end{table}
xtable(stat, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:57:31 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ 
##   \hline
## 1 & -0.0004 & 0.0091 & 0.9472 & 0.7733 & 0.5079 & 0.1369 & 0.5572 \\ 
##   2 & 0.0003 & 0.0165 & 0.8710 & 0.7504 & 0.5291 & 0.6360 & 2.9192 \\ 
##   3 & 0.0002 & 0.0101 & 0.9399 & 0.7827 & 0.5397 & 0.2777 & 0.2921 \\ 
##   4 & -0.0002 & 0.0103 & 0.9287 & 0.7694 & 0.5344 & 0.2500 & 0.7207 \\ 
##   5 & -0.0000 & 0.0139 & 0.8899 & 0.7710 & 0.5450 & 0.4320 & 1.7043 \\ 
##    \hline
## \end{tabular}
## \end{table}

Check for the portfolio sd can be calcualted by both the formula and sd of the simulated portfolio.

We have everything we need to perform our optimization. All we need now is to run this code on 8000 random portfolios. For that we will use a for loop.

Before we do that, we need to create empty vectors and matrix for storing our values.

#change nasset to no of assets in portfolio
num_port <- 10000
nasset <- nasset

# Creating a matrix to store the weights

all_wts1 <- matrix(nrow = num_port,
                  ncol = nasset)

# Creating an empty vector to store
# 8000 Portfolio returns

port_returns <- vector('numeric', length = num_port)

# Creating an empty vector to store
# 8000 Portfolio variances

port_risk.var1 <- vector('numeric', length = num_port)
port_risk.var2 <- vector('numeric', length = num_port)
port_risk.var3 <- vector('numeric', length = num_port)
port_risk.var4 <- vector('numeric', length = num_port)
port_risk.mad <- vector('numeric', length = num_port)

Sharpe_ratio.sd1 <- vector('numeric', length = num_port)
Sharpe_ratio.sd2 <- vector('numeric', length = num_port)
Sharpe_ratio.sd3 <- vector('numeric', length = num_port)
Sharpe_ratio.sd4 <- vector('numeric', length = num_port)
Sharpe_ratio.mad <- vector('numeric', length = num_port)

Next lets run the for loop 10000 times.

port.info <- matrix(0, nrow = 10000, ncol = 7)

ptm <- proc.time()

for (i in seq_along(port_returns)) {
  
  wts <- get_weights(nasset)
  
  # Storing weight in the matrix
  all_wts1[i,] <- wts
  
  # Portfolio returns
  
  port.info [i, ]<- portfolio_info (wts, as.matrix(train))
  
  # Storing Portfolio Returns values
  port_returns[i] <- port.info[i, 1]
  
  # Creating and storing portfolio risk
  port_risk.var1 [i] <- port.info[i, 2]
  port_risk.var2 [i] <- sqrt(1 - port.info[i, 3]^2)*port.info[i, 2]
  port_risk.var3 [i] <- sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.var4 [i] <- sqrt(1 - port.info[i, 3]^2)*sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.mad [i] <- 2*port.info[i, 2]*port.info[i, 4]*sqrt(port.info[i, 5]*(1-port.info[i, 5]))
  
  # Creating and storing Portfolio Sharpe Ratios
  # Assuming 0% Risk free rate
  
  Sharpe_ratio.sd1 [i] <- port_returns[i]/port_risk.var1 [i]
  Sharpe_ratio.sd2 [i] <- port_returns[i]/port_risk.var2 [i]
  Sharpe_ratio.sd3 [i] <- port_returns[i]/port_risk.var3 [i]
  Sharpe_ratio.sd4 [i] <- port_returns[i]/port_risk.var4 [i]
  Sharpe_ratio.mad [i] <- port_returns[i]/port_risk.mad [i]
}
proc.time()-ptm
##    user  system elapsed 
##  14.272   0.563  27.042
port.info.data <- as.data.frame(port.info)

ggplot(port.info.data, aes(x=V6, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Skewness") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V7, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Kurtosis") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V2, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatlity")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

We now create a data table to store all the values together (using sd).

# Storing the values in the table (5 columns and 8000 rows)
portfolio_values1 <- tibble(Return = port_returns,
                  Risk1 = port_risk.var1,
                  Risk2 = port_risk.var2,
                  Risk3 = port_risk.var3,
                  Risk4 = port_risk.var4,
                  Risk5 = port_risk.mad,
                  SharpeRatio1 = Sharpe_ratio.sd1,
                  SharpeRatio2 = Sharpe_ratio.sd2,
                  SharpeRatio3 = Sharpe_ratio.sd3,
                  SharpeRatio4 = Sharpe_ratio.sd4,
                  SharpeRatio5 = Sharpe_ratio.mad,
                  )
# Converting matrix to a tibble and changing column names
all_wts1 <- tk_tbl(all_wts1)
## Warning in tk_tbl.data.frame(as.data.frame(data), preserve_index, rename_index,
## : Warning: No index to preserve. Object otherwise converted to tibble
## successfully.
colnames(all_wts1) <- colnames(asset_returns)

# Combing all the values together
portfolio_values1 <- tk_tbl(cbind(all_wts1, portfolio_values1))
## Warning in tk_tbl.data.frame(cbind(all_wts1, portfolio_values1)): Warning: No
## index to preserve. Object otherwise converted to tibble successfully.

We have the weights in each asset with the risk and returns along with the Sharpe ratio of each portfolio. We use daily data to determine the portfolios.

Next lets look at the portfolios that matter the most.

min_var1 <- portfolio_values1[which.min(portfolio_values1$Risk1),]
min_var2 <- portfolio_values1[which.min(portfolio_values1$Risk2),]
min_var3 <- portfolio_values1[which.min(portfolio_values1$Risk3),]
min_var4 <- portfolio_values1[which.min(portfolio_values1$Risk4),]
min_mad <- portfolio_values1[which.min(portfolio_values1$Risk5),]
max_sr1 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio1),]
max_sr2 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio2),]
max_sr3 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio3),]
max_sr4 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio4),]
max_sr5 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio5),]
rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5)
## # A tibble: 10 × 16
##    ETH.USD     JNJ     MMM      T     V   Return   Risk1   Risk2   Risk3   Risk4
##      <dbl>   <dbl>   <dbl>  <dbl> <dbl>    <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
##  1  0.0227 0.354   0.0590  0.138  0.426 -1.28e-4 0.00740 0.00251 0.00463 0.00157
##  2  0.0233 0.313   0.0844  0.204  0.375 -2.35e-4 0.00759 0.00241 0.00472 0.00150
##  3  0.0348 0.293   0.0287  0.125  0.519  3.77e-5 0.00750 0.00249 0.00458 0.00152
##  4  0.0620 0.291   0.112   0.188  0.347 -1.96e-4 0.00775 0.00243 0.00476 0.00149
##  5  0.0126 0.477   0.0364  0.104  0.370 -1.80e-4 0.00747 0.00297 0.00483 0.00192
##  6  0.488  0.00288 0.0330  0.0196 0.456  1.06e-3 0.0164  0.00790 0.0111  0.00535
##  7  0.271  0.00635 0.00161 0.145  0.576  6.67e-4 0.0114  0.00441 0.00705 0.00273
##  8  0.359  0.0401  0.00897 0.0775 0.514  8.21e-4 0.0131  0.00582 0.00844 0.00375
##  9  0.171  0.233   0.00848 0.0119 0.575  4.82e-4 0.00915 0.00324 0.00550 0.00195
## 10  0.488  0.00288 0.0330  0.0196 0.456  1.06e-3 0.0164  0.00790 0.0111  0.00535
## # ℹ 6 more variables: Risk5 <dbl>, SharpeRatio1 <dbl>, SharpeRatio2 <dbl>,
## #   SharpeRatio3 <dbl>, SharpeRatio4 <dbl>, SharpeRatio5 <dbl>
xtable(rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5), digits = 6)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:17 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrrrrrrrrrrr}
##   \hline
##  & ETH.USD & JNJ & MMM & T & V & Return & Risk1 & Risk2 & Risk3 & Risk4 & Risk5 & SharpeRatio1 & SharpeRatio2 & SharpeRatio3 & SharpeRatio4 & SharpeRatio5 \\ 
##   \hline
## 1 & 0.022710 & 0.354100 & 0.058982 & 0.138196 & 0.426012 & -0.000128 & 0.007400 & 0.002509 & 0.004629 & 0.001570 & 0.005756 & -0.017309 & -0.051048 & -0.027671 & -0.081610 & -0.022255 \\ 
##   2 & 0.023299 & 0.313179 & 0.084429 & 0.204274 & 0.374819 & -0.000235 & 0.007586 & 0.002410 & 0.004723 & 0.001501 & 0.005900 & -0.030975 & -0.097501 & -0.049749 & -0.156597 & -0.039830 \\ 
##   3 & 0.034764 & 0.292748 & 0.028658 & 0.125214 & 0.518616 & 0.000038 & 0.007503 & 0.002486 & 0.004579 & 0.001517 & 0.005913 & 0.005031 & 0.015186 & 0.008243 & 0.024882 & 0.006383 \\ 
##   4 & 0.062040 & 0.290959 & 0.111770 & 0.188075 & 0.347155 & -0.000196 & 0.007747 & 0.002427 & 0.004760 & 0.001491 & 0.006081 & -0.025251 & -0.080598 & -0.041099 & -0.131183 & -0.032167 \\ 
##   5 & 0.012558 & 0.476790 & 0.036360 & 0.104291 & 0.370001 & -0.000180 & 0.007474 & 0.002966 & 0.004830 & 0.001917 & 0.005681 & -0.024035 & -0.060570 & -0.037192 & -0.093728 & -0.031623 \\ 
##   6 & 0.488372 & 0.002879 & 0.032951 & 0.019600 & 0.456199 & 0.001056 & 0.016395 & 0.007902 & 0.011095 & 0.005348 & 0.012058 & 0.064387 & 0.133585 & 0.095150 & 0.197409 & 0.087550 \\ 
##   7 & 0.271160 & 0.006346 & 0.001609 & 0.144851 & 0.576034 & 0.000667 & 0.011376 & 0.004410 & 0.007052 & 0.002734 & 0.008923 & 0.058611 & 0.151185 & 0.094540 & 0.243864 & 0.074724 \\ 
##   8 & 0.359309 & 0.040091 & 0.008968 & 0.077526 & 0.514106 & 0.000821 & 0.013110 & 0.005820 & 0.008436 & 0.003745 & 0.010003 & 0.062647 & 0.141109 & 0.097353 & 0.219283 & 0.082103 \\ 
##   9 & 0.170964 & 0.233317 & 0.008481 & 0.011883 & 0.575355 & 0.000482 & 0.009149 & 0.003239 & 0.005499 & 0.001947 & 0.007304 & 0.052632 & 0.148661 & 0.087568 & 0.247340 & 0.065929 \\ 
##   10 & 0.488372 & 0.002879 & 0.032951 & 0.019600 & 0.456199 & 0.001056 & 0.016395 & 0.007902 & 0.011095 & 0.005348 & 0.012058 & 0.064387 & 0.133585 & 0.095150 & 0.197409 & 0.087550 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change min_var1[1:nassets] and all the indexes after that accordingly
p1 <- cbind(min_var1[1:nasset], 252*min_var1[nasset+1], sqrt(252)*min_var1[nasset+2], sqrt(252)*min_var1[nasset+7])
p2 <- cbind(min_var2[1:nasset], 252*min_var2[nasset+1], sqrt(252)*min_var2[nasset+3], sqrt(252)*min_var2[nasset+8])
p3 <- cbind(min_var3[1:nasset], 252*min_var3[nasset+1], sqrt(252)*min_var3[nasset+4], sqrt(252)*min_var3[nasset+9])
p4 <- cbind(min_var4[1:nasset], 252*min_var4[nasset+1], sqrt(252)*min_var4[nasset+5], sqrt(252)*min_var4[nasset+10])
p5 <- cbind(min_mad[1:nasset], 252*min_mad[nasset+1], sqrt(252)*min_mad[nasset+6], sqrt(252)*min_mad[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:17 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.02271 & 0.02330 & 0.03476 & 0.06204 & 0.01256 \\ 
##   2 & 0.35410 & 0.31318 & 0.29275 & 0.29096 & 0.47679 \\ 
##   3 & 0.05898 & 0.08443 & 0.02866 & 0.11177 & 0.03636 \\ 
##   4 & 0.13820 & 0.20427 & 0.12521 & 0.18808 & 0.10429 \\ 
##   5 & 0.42601 & 0.37482 & 0.51862 & 0.34716 & 0.37000 \\ 
##   6 & -0.03228 & -0.05922 & 0.00951 & -0.04930 & -0.04527 \\ 
##   7 & 0.11748 & 0.03826 & 0.07269 & 0.02367 & 0.09018 \\ 
##   8 & -0.27477 & -1.54777 & 0.13086 & -2.08247 & -0.50200 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change max_sr[1:nassets] and all the indexes after that accordingly
p1 <- cbind(max_sr1[1:nasset], 252*max_sr1[nasset+1], sqrt(252)*max_sr1[nasset+2], sqrt(252)*max_sr1[nasset+7])
p2 <- cbind(max_sr2[1:nasset], 252*max_sr2[nasset+1], sqrt(252)*max_sr2[nasset+3], sqrt(252)*max_sr2[nasset+8])
p3 <- cbind(max_sr3[1:nasset], 252*max_sr3[nasset+1], sqrt(252)*max_sr3[nasset+4], sqrt(252)*max_sr3[nasset+9])
p4 <- cbind(max_sr4[1:nasset], 252*max_sr4[nasset+1], sqrt(252)*max_sr4[nasset+5], sqrt(252)*max_sr4[nasset+10])
p5 <- cbind(max_sr5[1:nasset], 252*max_sr5[nasset+1], sqrt(252)*max_sr5[nasset+6], sqrt(252)*max_sr5[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:17 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.48837 & 0.27116 & 0.35931 & 0.17096 & 0.48837 \\ 
##   2 & 0.00288 & 0.00635 & 0.04009 & 0.23332 & 0.00288 \\ 
##   3 & 0.03295 & 0.00161 & 0.00897 & 0.00848 & 0.03295 \\ 
##   4 & 0.01960 & 0.14485 & 0.07753 & 0.01188 & 0.01960 \\ 
##   5 & 0.45620 & 0.57603 & 0.51411 & 0.57536 & 0.45620 \\ 
##   6 & 0.26602 & 0.16802 & 0.20697 & 0.12134 & 0.26602 \\ 
##   7 & 0.26027 & 0.07001 & 0.13392 & 0.03090 & 0.19141 \\ 
##   8 & 1.02211 & 2.39999 & 1.54544 & 3.92640 & 1.38982 \\ 
##    \hline
## \end{tabular}
## \end{table}
nasset <- ncol(asset_returns)
w1 <- min_var1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w2 <- min_var2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w3 <- min_var3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w4 <- min_var4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w5 <- min_mad[, 1:nasset] %>% gather () %>% arrange(desc(value))
w6 <- max_sr1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w7 <- max_sr2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w8 <- max_sr3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w9 <- max_sr4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w10 <- max_sr5[, 1:nasset] %>% gather () %>% arrange(desc(value))

xtable(cbind(head (w1, 10), head (w2, 10), head (w3, 10), head (w4, 10), head (w5, 10), head (w6, 10), head (w7, 10), head (w8, 10), head (w9, 10), head (w10, 10)), digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:17 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rlrlrlrlrlrlrlrlrlrlr}
##   \hline
##  & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value \\ 
##   \hline
## 1 & V & 0.4260 & V & 0.3748 & V & 0.5186 & V & 0.3472 & JNJ & 0.4768 & ETH.USD & 0.4884 & V & 0.5760 & V & 0.5141 & V & 0.5754 & ETH.USD & 0.4884 \\ 
##   2 & JNJ & 0.3541 & JNJ & 0.3132 & JNJ & 0.2927 & JNJ & 0.2910 & V & 0.3700 & V & 0.4562 & ETH.USD & 0.2712 & ETH.USD & 0.3593 & JNJ & 0.2333 & V & 0.4562 \\ 
##   3 & T & 0.1382 & T & 0.2043 & T & 0.1252 & T & 0.1881 & T & 0.1043 & MMM & 0.0330 & T & 0.1449 & T & 0.0775 & ETH.USD & 0.1710 & MMM & 0.0330 \\ 
##   4 & MMM & 0.0590 & MMM & 0.0844 & ETH.USD & 0.0348 & MMM & 0.1118 & MMM & 0.0364 & T & 0.0196 & JNJ & 0.0063 & JNJ & 0.0401 & T & 0.0119 & T & 0.0196 \\ 
##   5 & ETH.USD & 0.0227 & ETH.USD & 0.0233 & MMM & 0.0287 & ETH.USD & 0.0620 & ETH.USD & 0.0126 & JNJ & 0.0029 & MMM & 0.0016 & MMM & 0.0090 & MMM & 0.0085 & JNJ & 0.0029 \\ 
##    \hline
## \end{tabular}
## \end{table}

Lets plot the weights of each portfolio. First with the minimum variance portfolio.

p1 <- min_var4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset,Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Minimum Risk Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p1)
p2 <- max_sr4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset, Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Tangency Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p2)
#convert daily return, risk, SR to annualized ones

portfolio_values1_annual <- portfolio_values1 %>% mutate(Return = Return * 252) %>% mutate(Risk1 = Risk1 * sqrt(252), Risk2 = Risk2 * sqrt(252), Risk3 = Risk3 * sqrt(252), Risk4 = Risk4 * sqrt(252), Risk5 = Risk5 * sqrt(252)) %>% mutate(SharpeRatio1 = SharpeRatio1 * sqrt(252), SharpeRatio2 = SharpeRatio2 * sqrt(252), SharpeRatio3 = SharpeRatio3 * sqrt(252), SharpeRatio4 = SharpeRatio4 * sqrt(252), SharpeRatio5 = SharpeRatio5 * sqrt(252))
min_var1.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk1),]
min_var2.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk2),]
min_var3.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk3),]
min_var4.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk4),]
min_mad.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk5),]
max_sr1.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio1),]
max_sr2.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio2),]
max_sr3.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio3),]
max_sr4.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio4),]
max_sr5.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio5),]

rbind(min_var1.a, min_var2.a, min_var3.a, min_var4.a, min_mad.a, max_sr1.a, max_sr2.a, max_sr3.a, max_sr4.a, max_sr5.a)
## # A tibble: 10 × 16
##    ETH.USD     JNJ     MMM      T     V   Return Risk1  Risk2  Risk3  Risk4
##      <dbl>   <dbl>   <dbl>  <dbl> <dbl>    <dbl> <dbl>  <dbl>  <dbl>  <dbl>
##  1  0.0227 0.354   0.0590  0.138  0.426 -0.0323  0.117 0.0398 0.0735 0.0249
##  2  0.0233 0.313   0.0844  0.204  0.375 -0.0592  0.120 0.0383 0.0750 0.0238
##  3  0.0348 0.293   0.0287  0.125  0.519  0.00951 0.119 0.0395 0.0727 0.0241
##  4  0.0620 0.291   0.112   0.188  0.347 -0.0493  0.123 0.0385 0.0756 0.0237
##  5  0.0126 0.477   0.0364  0.104  0.370 -0.0453  0.119 0.0471 0.0767 0.0304
##  6  0.488  0.00288 0.0330  0.0196 0.456  0.266   0.260 0.125  0.176  0.0849
##  7  0.271  0.00635 0.00161 0.145  0.576  0.168   0.181 0.0700 0.112  0.0434
##  8  0.359  0.0401  0.00897 0.0775 0.514  0.207   0.208 0.0924 0.134  0.0595
##  9  0.171  0.233   0.00848 0.0119 0.575  0.121   0.145 0.0514 0.0873 0.0309
## 10  0.488  0.00288 0.0330  0.0196 0.456  0.266   0.260 0.125  0.176  0.0849
## # ℹ 6 more variables: Risk5 <dbl>, SharpeRatio1 <dbl>, SharpeRatio2 <dbl>,
## #   SharpeRatio3 <dbl>, SharpeRatio4 <dbl>, SharpeRatio5 <dbl>
p1 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk1, y = Return, color = SharpeRatio1)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (SD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk1,
                 y = Return), data = min_var1.a, color = 'orange') +
  geom_point(aes(x = Risk1,
                 y = Return), data = max_sr1.a, color = 'orange4', shape = 18)
ggplotly(p1)
p2 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk2, y = Return, color = SharpeRatio2)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VEV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk2,
                 y = Return), data = min_var2.a, color = 'green') +
  geom_point(aes(x = Risk2,
                 y = Return), data = max_sr2.a, color = 'green4', shape = 18)
ggplotly(p2)
p3 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk3, y = Return, color = SharpeRatio3)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VES)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk3,
                 y = Return), data = min_var3.a, color = 'red') +
  geom_point(aes(x = Risk3,
                 y = Return), data = max_sr3.a, color = 'red4', shape = 18)
ggplotly(p3)
p4 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk4, y = Return, color = SharpeRatio4)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VESV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk4,
                 y = Return), data = min_var4.a, color = 'purple') +
  geom_point(aes(x = Risk4,
                 y = Return), data = max_sr4.a, color = 'purple4', shape = 18)
ggplotly(p4)
p5 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk5, y = Return, color = SharpeRatio5)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (MAD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk5,
                 y = Return), data = min_mad.a, color = 'blue') +
  geom_point(aes(x = Risk5,
                 y = Return), data = max_sr5.a, color = 'blue4', shape = 18)
ggplotly(p5)

Plots cummulative returns of the test sample

MVP1 <- as.matrix(test)%*%as.vector(as.numeric(min_var1[1:nasset]))
MVP2 <- as.matrix(test)%*%as.vector(as.numeric(min_var2[1:nasset]))
MVP3 <- as.matrix(test)%*%as.vector(as.numeric(min_var3[1:nasset]))
MVP4 <- as.matrix(test)%*%as.vector(as.numeric(min_var4[1:nasset]))
MVP5 <- as.matrix(test)%*%as.vector(as.numeric(min_mad[1:nasset]))
TP1<-as.matrix(test)%*%as.vector(as.numeric(max_sr1[1:nasset]))
TP2<-as.matrix(test)%*%as.vector(as.numeric(max_sr2[1:nasset]))
TP3<-as.matrix(test)%*%as.vector(as.numeric(max_sr3[1:nasset]))
TP4<-as.matrix(test)%*%as.vector(as.numeric(max_sr4[1:nasset]))
TP5<-as.matrix(test)%*%as.vector(as.numeric(max_sr5[1:nasset]))
EWQ<-as.matrix(test)%*%as.vector(rep(1/nasset, nasset))
assets <- c("MVP1", "MVP2", "MVP3", "MVP4", "MVP5", "TP1", "TP2", "TP3", "TP4", "TP5", "EWQ")

#Portfolios <- merge(test[, 1], cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))[, -c(1)]

Portfolios <- cbind.data.frame(cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))

colnames(Portfolios) <- assets
# Define start and end dates
start_date <- as.Date("2023-01-01")
end_date <- as.Date("2023-12-31")
# Create a sequence of dates
date_sequence <- seq(start_date, end_date, by = "day")
#date_sequence

# Number of last values to select
nTemp <- nrow(Portfolios)

# Select the last 'n' values from the vector
TestDates <- date_sequence[(length(date_sequence) - nTemp + 1):length(date_sequence)]
#TestDates
row.names(Portfolios) <- TestDates
dygraph(Portfolios, main = 'Cummulative Returns for Test Period')%>%
dySeries('MVP1', label = 'MVP', col = "orange") %>%
dySeries('MVP2', label = 'MRP2', col = "green") %>%
dySeries('MVP3', label = 'MRP3', col = "red") %>%  
dySeries('MVP4', label = 'MRP4', col = "purple") %>%
dySeries('MVP5', label = 'MRP5', col = "blue") %>%
dySeries('TP1', label = 'TP', col = "orange", drawPoints = TRUE) %>% 
dySeries('TP2', label = 'MRRP2', col = "green", drawPoints = TRUE) %>%
dySeries('TP3', label = 'MRRP3', col = "red", drawPoints = TRUE) %>%  
dySeries('TP4', label = 'MRRP4', col = "purple", drawPoints = TRUE) %>% 
dySeries('TP5', label = 'MRRP5', col = "blue", drawPoints = TRUE) %>%  
dySeries('EWQ', label = 'EWQ', col = "black") %>% 
dyRangeSelector(height = 30)%>%
  dyLegend(width = 500)

Choose cummulative return from volatility correlations - lowest average risk

CumReturnVolCorr_low_avg_risk <- cumsum(TP2)
CumReturnVolCorr_low_avg_risk
##  [1]  8.644974e-03 -8.485550e-04  4.666188e-03  2.425799e-04 -4.837901e-03
##  [6] -1.362481e-03  1.347273e-02  1.190016e-02 -5.841199e-05  1.173260e-03
## [11]  7.708888e-03  2.616655e-02  4.255356e-02  4.523415e-02  3.342379e-02
## [16]  2.177181e-02  4.032051e-02  4.767822e-02  6.247844e-02  6.842389e-02
## [21]  7.555266e-02  8.403487e-02  8.617913e-02  8.377437e-02  1.112817e-01
## [26]  1.145869e-01  1.096792e-01  1.054741e-01  1.206355e-01  1.097702e-01
## [31]  1.122827e-01  1.235289e-01  1.181603e-01  1.392235e-01  1.431762e-01
## [36]  1.357805e-01  1.357629e-01  1.372262e-01  1.483155e-01  1.541945e-01
## [41]  1.691705e-01  1.805036e-01  1.700140e-01  1.900205e-01  1.884934e-01
## [46]  1.722828e-01  1.745226e-01  1.884064e-01  1.889510e-01  1.748091e-01
## [51]  1.747846e-01  1.749453e-01  1.695576e-01  1.805253e-01  1.891575e-01
## [56]  1.799351e-01  1.974255e-01  1.985633e-01  1.933856e-01

Portfolio selected from emperical_DBSCAN_2023_lowest_risk

#Import data

emperical_DBSCAN_2023_lowest_risk <- read.csv("~/Desktop/PO/DBSCAN/EMP/2023/emperical_DBSCAN_2023_lowest_risk.csv")

#remove the date column
asset_prices<-emperical_DBSCAN_2023_lowest_risk[,-1]
# calculate returns
ret_tidy1 = apply(asset_prices,2, log)
head(ret_tidy1)
##            KO      PEP       PG        V      WMT
## [1,] 4.088750 5.138328 4.977250 5.320976 3.843580
## [2,] 4.088274 5.135873 4.981595 5.345835 3.844694
## [3,] 4.076765 5.125369 4.969102 5.338754 3.841279
## [4,] 4.095874 5.147704 4.992635 5.369723 3.865483
## [5,] 4.083335 5.137882 4.980346 5.373619 3.852937
## [6,] 4.075639 5.129595 4.979359 5.384945 3.852316
ret_tidy2 = diff(ret_tidy1)
head(ret_tidy2)
##                 KO          PEP            PG            V           WMT
## [1,] -0.0004766847 -0.002455439  0.0043449463  0.024858315  0.0011135850
## [2,] -0.0115090727 -0.010503589 -0.0124932234 -0.007080053 -0.0034141652
## [3,]  0.0191088946  0.022334829  0.0235336046  0.030968202  0.0242036731
## [4,] -0.0125387441 -0.009821764 -0.0122893509  0.003895977 -0.0125459523
## [5,] -0.0076961487 -0.008287200 -0.0009870545  0.011326329 -0.0006209848
## [6,] -0.0019333764  0.001123984 -0.0081309353  0.004557899  0.0087288200
ret_tidy = exp (ret_tidy2) - 1 #simple returns
#remove first row
asset_returns <- ret_tidy[-1,]

#no.of assets in the portfolio 
nasset<-ncol(asset_returns)

# testing and training data sets (each data set has 252 observations)
# Divide the data set in to 3:1 (75% training and 25% testing)
# testing period - January - September (189 data points)
# training period - October - December (62 data points)

n.total<-252
n.train<- 189

train = asset_returns[1:n.train,]
test = asset_returns[-(1:(n.train)),]
##summary statistics 
rhosign<-apply(as.matrix(train), MARGIN=2, FUN=rho.cal)
rhovol<-apply(as.matrix(train), MARGIN=2, FUN=rho.vol)
assetsummary<-data.frame(apply(train, 2, mean), apply(train, 2, sd), rhovol, rhosign, apply(train, 2, skewness),
                 apply(train, 2, kurtosis))
xtable(assetsummary, digits=4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:22 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrr}
##   \hline
##  & apply.train..2..mean. & apply.train..2..sd. & rhovol & rhosign & apply.train..2..skewness. & apply.train..2..kurtosis. \\ 
##   \hline
## KO & -0.0008 & 0.0084 & 0.8623 & 0.7384 & -0.9780 & 5.1824 \\ 
##   PEP & -0.0004 & 0.0095 & 0.8571 & 0.7284 & -0.7361 & 4.0926 \\ 
##   PG & -0.0002 & 0.0092 & 0.9194 & 0.7529 & 0.2519 & 1.2707 \\ 
##   V & 0.0006 & 0.0101 & 0.9360 & 0.7797 & 0.2072 & 0.6578 \\ 
##   WMT & 0.0006 & 0.0084 & 0.9356 & 0.7931 & -0.2408 & 0.2941 \\ 
##    \hline
## \end{tabular}
## \end{table}
plot(train, legend.loc=1)
## Warning in plot.window(...): "legend.loc" is not a graphical parameter
## Warning in plot.xy(xy, type, ...): "legend.loc" is not a graphical parameter
## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter

## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter
## Warning in box(...): "legend.loc" is not a graphical parameter
## Warning in title(...): "legend.loc" is not a graphical parameter

Lets calculate annualized portfolio return, risk, and gamma from the simulated portfolio returns with portfolio weights. (simulated weights)

## portfolio return, sd and gamma
## w is the random weight
## data = train or test
portfolio_info = function(w, data){
  port.data <- data%*%as.vector(w)
  port.cdf <- ecdf(port.data)
  port.return <- mean (port.data)
  port.sd <- sd (port.data)
  port.signrho <- cor (port.data - port.return, sign(port.data - port.return))
# port.signrho3 <- cor (sign(port.data - port.return), (port.data - port.return)^3)
# port.skewrho <- cor (port.data - port.return, (port.data - port.return)^2)
  port.volcor <- cor (abs(port.data - port.return), (port.data - port.return)^2) #volatlity correlation
  port.skewness <- skewness (port.data) #mu_3/sigma^3
  port.kurtosis <- kurtosis (port.data) #excess kurtosis mu_4/sigma^4 - 3
  return(c(port.return, port.sd, port.volcor, port.signrho, port.cdf(port.return), port.skewness, port.kurtosis))
}
# In stat matrix and weight matrix nrow = no.of assets in the portfolio (need to change), ncol is fixed to 7 , for loop i in 1:nrow
stat<-matrix(0, nrow = nasset, ncol = 7)
weight<-matrix(0, nrow = nasset, ncol = nasset)
for (i in 1:nasset){
weight[i, ] <- get_weights(nasset)
stat[i, ] <- portfolio_info (weight[i, ], as.matrix(train))
}
xtable(weight, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:22 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.1129 & 0.3268 & 0.0426 & 0.3789 & 0.1389 \\ 
##   2 & 0.0884 & 0.3115 & 0.2971 & 0.3018 & 0.0012 \\ 
##   3 & 0.1587 & 0.3369 & 0.2280 & 0.1066 & 0.1698 \\ 
##   4 & 0.3393 & 0.3400 & 0.1840 & 0.0638 & 0.0729 \\ 
##   5 & 0.3193 & 0.2480 & 0.1432 & 0.1952 & 0.0943 \\ 
##    \hline
## \end{tabular}
## \end{table}
xtable(stat, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:22 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ 
##   \hline
## 1 & 0.0001 & 0.0069 & 0.9139 & 0.7828 & 0.4656 & -0.1696 & 0.9569 \\ 
##   2 & -0.0001 & 0.0071 & 0.9127 & 0.7693 & 0.5079 & -0.1876 & 0.9527 \\ 
##   3 & -0.0001 & 0.0072 & 0.9015 & 0.7634 & 0.5238 & -0.4351 & 1.7819 \\ 
##   4 & -0.0004 & 0.0075 & 0.8806 & 0.7557 & 0.4868 & -0.6806 & 2.9719 \\ 
##   5 & -0.0002 & 0.0070 & 0.8954 & 0.7619 & 0.4921 & -0.4896 & 2.0651 \\ 
##    \hline
## \end{tabular}
## \end{table}

Check for the portfolio sd can be calcualted by both the formula and sd of the simulated portfolio.

We have everything we need to perform our optimization. All we need now is to run this code on 8000 random portfolios. For that we will use a for loop.

Before we do that, we need to create empty vectors and matrix for storing our values.

#change nasset to no of assets in portfolio
num_port <- 10000
nasset <- nasset

# Creating a matrix to store the weights

all_wts1 <- matrix(nrow = num_port,
                  ncol = nasset)

# Creating an empty vector to store
# 8000 Portfolio returns

port_returns <- vector('numeric', length = num_port)

# Creating an empty vector to store
# 8000 Portfolio variances

port_risk.var1 <- vector('numeric', length = num_port)
port_risk.var2 <- vector('numeric', length = num_port)
port_risk.var3 <- vector('numeric', length = num_port)
port_risk.var4 <- vector('numeric', length = num_port)
port_risk.mad <- vector('numeric', length = num_port)

Sharpe_ratio.sd1 <- vector('numeric', length = num_port)
Sharpe_ratio.sd2 <- vector('numeric', length = num_port)
Sharpe_ratio.sd3 <- vector('numeric', length = num_port)
Sharpe_ratio.sd4 <- vector('numeric', length = num_port)
Sharpe_ratio.mad <- vector('numeric', length = num_port)

Next lets run the for loop 10000 times.

port.info <- matrix(0, nrow = 10000, ncol = 7)

ptm <- proc.time()

for (i in seq_along(port_returns)) {
  
  wts <- get_weights(nasset)
  
  # Storing weight in the matrix
  all_wts1[i,] <- wts
  
  # Portfolio returns
  
  port.info [i, ]<- portfolio_info (wts, as.matrix(train))
  
  # Storing Portfolio Returns values
  port_returns[i] <- port.info[i, 1]
  
  # Creating and storing portfolio risk
  port_risk.var1 [i] <- port.info[i, 2]
  port_risk.var2 [i] <- sqrt(1 - port.info[i, 3]^2)*port.info[i, 2]
  port_risk.var3 [i] <- sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.var4 [i] <- sqrt(1 - port.info[i, 3]^2)*sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.mad [i] <- 2*port.info[i, 2]*port.info[i, 4]*sqrt(port.info[i, 5]*(1-port.info[i, 5]))
  
  # Creating and storing Portfolio Sharpe Ratios
  # Assuming 0% Risk free rate
  
  Sharpe_ratio.sd1 [i] <- port_returns[i]/port_risk.var1 [i]
  Sharpe_ratio.sd2 [i] <- port_returns[i]/port_risk.var2 [i]
  Sharpe_ratio.sd3 [i] <- port_returns[i]/port_risk.var3 [i]
  Sharpe_ratio.sd4 [i] <- port_returns[i]/port_risk.var4 [i]
  Sharpe_ratio.mad [i] <- port_returns[i]/port_risk.mad [i]
}
proc.time()-ptm
##    user  system elapsed 
##   9.850   0.130  10.492
port.info.data <- as.data.frame(port.info)

ggplot(port.info.data, aes(x=V6, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Skewness") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V7, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Kurtosis") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V2, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatlity")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

We now create a data table to store all the values together (using sd).

# Storing the values in the table (5 columns and 8000 rows)
portfolio_values1 <- tibble(Return = port_returns,
                  Risk1 = port_risk.var1,
                  Risk2 = port_risk.var2,
                  Risk3 = port_risk.var3,
                  Risk4 = port_risk.var4,
                  Risk5 = port_risk.mad,
                  SharpeRatio1 = Sharpe_ratio.sd1,
                  SharpeRatio2 = Sharpe_ratio.sd2,
                  SharpeRatio3 = Sharpe_ratio.sd3,
                  SharpeRatio4 = Sharpe_ratio.sd4,
                  SharpeRatio5 = Sharpe_ratio.mad,
                  )
# Converting matrix to a tibble and changing column names
all_wts1 <- tk_tbl(all_wts1)
## Warning in tk_tbl.data.frame(as.data.frame(data), preserve_index, rename_index,
## : Warning: No index to preserve. Object otherwise converted to tibble
## successfully.
colnames(all_wts1) <- colnames(asset_returns)

# Combing all the values together
portfolio_values1 <- tk_tbl(cbind(all_wts1, portfolio_values1))
## Warning in tk_tbl.data.frame(cbind(all_wts1, portfolio_values1)): Warning: No
## index to preserve. Object otherwise converted to tibble successfully.

We have the weights in each asset with the risk and returns along with the Sharpe ratio of each portfolio. We use daily data to determine the portfolios.

Next lets look at the portfolios that matter the most.

min_var1 <- portfolio_values1[which.min(portfolio_values1$Risk1),]
min_var2 <- portfolio_values1[which.min(portfolio_values1$Risk2),]
min_var3 <- portfolio_values1[which.min(portfolio_values1$Risk3),]
min_var4 <- portfolio_values1[which.min(portfolio_values1$Risk4),]
min_mad <- portfolio_values1[which.min(portfolio_values1$Risk5),]
max_sr1 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio1),]
max_sr2 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio2),]
max_sr3 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio3),]
max_sr4 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio4),]
max_sr5 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio5),]
rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5)
## # A tibble: 10 × 16
##         KO    PEP     PG      V   WMT     Return   Risk1   Risk2   Risk3   Risk4
##      <dbl>  <dbl>  <dbl>  <dbl> <dbl>      <dbl>   <dbl>   <dbl>   <dbl>   <dbl>
##  1 0.277   0.0105 0.149  0.276  0.287  0.0000871 0.00655 0.00276 0.00414 0.00175
##  2 0.0326  0.0264 0.404  0.346  0.190  0.000217  0.00691 0.00270 0.00439 0.00171
##  3 0.206   0.0906 0.0983 0.287  0.319  0.000144  0.00657 0.00274 0.00411 0.00172
##  4 0.153   0.0331 0.0517 0.0474 0.715  0.000333  0.00737 0.00277 0.00445 0.00167
##  5 0.393   0.0138 0.106  0.264  0.223 -0.0000487 0.00659 0.00280 0.00424 0.00180
##  6 0.00103 0.0178 0.0531 0.432  0.496  0.000545  0.00712 0.00285 0.00445 0.00178
##  7 0.00103 0.0178 0.0531 0.432  0.496  0.000545  0.00712 0.00285 0.00445 0.00178
##  8 0.00103 0.0178 0.0531 0.432  0.496  0.000545  0.00712 0.00285 0.00445 0.00178
##  9 0.00103 0.0178 0.0531 0.432  0.496  0.000545  0.00712 0.00285 0.00445 0.00178
## 10 0.00103 0.0178 0.0531 0.432  0.496  0.000545  0.00712 0.00285 0.00445 0.00178
## # ℹ 6 more variables: Risk5 <dbl>, SharpeRatio1 <dbl>, SharpeRatio2 <dbl>,
## #   SharpeRatio3 <dbl>, SharpeRatio4 <dbl>, SharpeRatio5 <dbl>
xtable(rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5), digits = 6)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:51 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrrrrrrrrrrr}
##   \hline
##  & KO & PEP & PG & V & WMT & Return & Risk1 & Risk2 & Risk3 & Risk4 & Risk5 & SharpeRatio1 & SharpeRatio2 & SharpeRatio3 & SharpeRatio4 & SharpeRatio5 \\ 
##   \hline
## 1 & 0.277157 & 0.010452 & 0.149149 & 0.276083 & 0.287159 & 0.000087 & 0.006546 & 0.002757 & 0.004144 & 0.001745 & 0.005063 & 0.013305 & 0.031593 & 0.021015 & 0.049903 & 0.017200 \\ 
##   2 & 0.032572 & 0.026419 & 0.404454 & 0.346265 & 0.190290 & 0.000217 & 0.006909 & 0.002695 & 0.004391 & 0.001713 & 0.005334 & 0.031435 & 0.080583 & 0.049464 & 0.126801 & 0.040714 \\ 
##   3 & 0.205782 & 0.090567 & 0.098272 & 0.286821 & 0.318559 & 0.000144 & 0.006573 & 0.002743 & 0.004110 & 0.001715 & 0.005124 & 0.021971 & 0.052648 & 0.035137 & 0.084198 & 0.028186 \\ 
##   4 & 0.152583 & 0.033071 & 0.051694 & 0.047389 & 0.715263 & 0.000333 & 0.007370 & 0.002775 & 0.004445 & 0.001674 & 0.005874 & 0.045126 & 0.119854 & 0.074818 & 0.198715 & 0.056615 \\ 
##   5 & 0.392825 & 0.013822 & 0.106055 & 0.264187 & 0.223111 & -0.000049 & 0.006587 & 0.002797 & 0.004242 & 0.001801 & 0.005039 & -0.007397 & -0.017421 & -0.011488 & -0.027054 & -0.009669 \\ 
##   6 & 0.001029 & 0.017775 & 0.053080 & 0.431652 & 0.496464 & 0.000545 & 0.007117 & 0.002846 & 0.004449 & 0.001779 & 0.005521 & 0.076637 & 0.191658 & 0.122588 & 0.306575 & 0.098802 \\ 
##   7 & 0.001029 & 0.017775 & 0.053080 & 0.431652 & 0.496464 & 0.000545 & 0.007117 & 0.002846 & 0.004449 & 0.001779 & 0.005521 & 0.076637 & 0.191658 & 0.122588 & 0.306575 & 0.098802 \\ 
##   8 & 0.001029 & 0.017775 & 0.053080 & 0.431652 & 0.496464 & 0.000545 & 0.007117 & 0.002846 & 0.004449 & 0.001779 & 0.005521 & 0.076637 & 0.191658 & 0.122588 & 0.306575 & 0.098802 \\ 
##   9 & 0.001029 & 0.017775 & 0.053080 & 0.431652 & 0.496464 & 0.000545 & 0.007117 & 0.002846 & 0.004449 & 0.001779 & 0.005521 & 0.076637 & 0.191658 & 0.122588 & 0.306575 & 0.098802 \\ 
##   10 & 0.001029 & 0.017775 & 0.053080 & 0.431652 & 0.496464 & 0.000545 & 0.007117 & 0.002846 & 0.004449 & 0.001779 & 0.005521 & 0.076637 & 0.191658 & 0.122588 & 0.306575 & 0.098802 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change min_var1[1:nassets] and all the indexes after that accordingly
p1 <- cbind(min_var1[1:nasset], 252*min_var1[nasset+1], sqrt(252)*min_var1[nasset+2], sqrt(252)*min_var1[nasset+7])
p2 <- cbind(min_var2[1:nasset], 252*min_var2[nasset+1], sqrt(252)*min_var2[nasset+3], sqrt(252)*min_var2[nasset+8])
p3 <- cbind(min_var3[1:nasset], 252*min_var3[nasset+1], sqrt(252)*min_var3[nasset+4], sqrt(252)*min_var3[nasset+9])
p4 <- cbind(min_var4[1:nasset], 252*min_var4[nasset+1], sqrt(252)*min_var4[nasset+5], sqrt(252)*min_var4[nasset+10])
p5 <- cbind(min_mad[1:nasset], 252*min_mad[nasset+1], sqrt(252)*min_mad[nasset+6], sqrt(252)*min_mad[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:51 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.27716 & 0.03257 & 0.20578 & 0.15258 & 0.39282 \\ 
##   2 & 0.01045 & 0.02642 & 0.09057 & 0.03307 & 0.01382 \\ 
##   3 & 0.14915 & 0.40445 & 0.09827 & 0.05169 & 0.10605 \\ 
##   4 & 0.27608 & 0.34627 & 0.28682 & 0.04739 & 0.26419 \\ 
##   5 & 0.28716 & 0.19029 & 0.31856 & 0.71526 & 0.22311 \\ 
##   6 & 0.02195 & 0.05473 & 0.03640 & 0.08381 & -0.01228 \\ 
##   7 & 0.10391 & 0.04278 & 0.06525 & 0.02657 & 0.08000 \\ 
##   8 & 0.21121 & 1.27921 & 0.55779 & 3.15450 & -0.15349 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change max_sr[1:nassets] and all the indexes after that accordingly
p1 <- cbind(max_sr1[1:nasset], 252*max_sr1[nasset+1], sqrt(252)*max_sr1[nasset+2], sqrt(252)*max_sr1[nasset+7])
p2 <- cbind(max_sr2[1:nasset], 252*max_sr2[nasset+1], sqrt(252)*max_sr2[nasset+3], sqrt(252)*max_sr2[nasset+8])
p3 <- cbind(max_sr3[1:nasset], 252*max_sr3[nasset+1], sqrt(252)*max_sr3[nasset+4], sqrt(252)*max_sr3[nasset+9])
p4 <- cbind(max_sr4[1:nasset], 252*max_sr4[nasset+1], sqrt(252)*max_sr4[nasset+5], sqrt(252)*max_sr4[nasset+10])
p5 <- cbind(max_sr5[1:nasset], 252*max_sr5[nasset+1], sqrt(252)*max_sr5[nasset+6], sqrt(252)*max_sr5[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:51 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.00103 & 0.00103 & 0.00103 & 0.00103 & 0.00103 \\ 
##   2 & 0.01777 & 0.01777 & 0.01777 & 0.01777 & 0.01777 \\ 
##   3 & 0.05308 & 0.05308 & 0.05308 & 0.05308 & 0.05308 \\ 
##   4 & 0.43165 & 0.43165 & 0.43165 & 0.43165 & 0.43165 \\ 
##   5 & 0.49646 & 0.49646 & 0.49646 & 0.49646 & 0.49646 \\ 
##   6 & 0.13745 & 0.13745 & 0.13745 & 0.13745 & 0.13745 \\ 
##   7 & 0.11298 & 0.04518 & 0.07063 & 0.02824 & 0.08764 \\ 
##   8 & 1.21657 & 3.04248 & 1.94602 & 4.86672 & 1.56843 \\ 
##    \hline
## \end{tabular}
## \end{table}
nasset <- ncol(asset_returns)
w1 <- min_var1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w2 <- min_var2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w3 <- min_var3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w4 <- min_var4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w5 <- min_mad[, 1:nasset] %>% gather () %>% arrange(desc(value))
w6 <- max_sr1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w7 <- max_sr2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w8 <- max_sr3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w9 <- max_sr4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w10 <- max_sr5[, 1:nasset] %>% gather () %>% arrange(desc(value))

xtable(cbind(head (w1, 10), head (w2, 10), head (w3, 10), head (w4, 10), head (w5, 10), head (w6, 10), head (w7, 10), head (w8, 10), head (w9, 10), head (w10, 10)), digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:51 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rlrlrlrlrlrlrlrlrlrlr}
##   \hline
##  & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value \\ 
##   \hline
## 1 & WMT & 0.2872 & PG & 0.4045 & WMT & 0.3186 & WMT & 0.7153 & KO & 0.3928 & WMT & 0.4965 & WMT & 0.4965 & WMT & 0.4965 & WMT & 0.4965 & WMT & 0.4965 \\ 
##   2 & KO & 0.2772 & V & 0.3463 & V & 0.2868 & KO & 0.1526 & V & 0.2642 & V & 0.4317 & V & 0.4317 & V & 0.4317 & V & 0.4317 & V & 0.4317 \\ 
##   3 & V & 0.2761 & WMT & 0.1903 & KO & 0.2058 & PG & 0.0517 & WMT & 0.2231 & PG & 0.0531 & PG & 0.0531 & PG & 0.0531 & PG & 0.0531 & PG & 0.0531 \\ 
##   4 & PG & 0.1491 & KO & 0.0326 & PG & 0.0983 & V & 0.0474 & PG & 0.1061 & PEP & 0.0178 & PEP & 0.0178 & PEP & 0.0178 & PEP & 0.0178 & PEP & 0.0178 \\ 
##   5 & PEP & 0.0105 & PEP & 0.0264 & PEP & 0.0906 & PEP & 0.0331 & PEP & 0.0138 & KO & 0.0010 & KO & 0.0010 & KO & 0.0010 & KO & 0.0010 & KO & 0.0010 \\ 
##    \hline
## \end{tabular}
## \end{table}

Lets plot the weights of each portfolio. First with the minimum variance portfolio.

p1 <- min_var4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset,Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Minimum Risk Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p1)
p2 <- max_sr4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset, Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Tangency Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p2)
#convert daily return, risk, SR to annualized ones

portfolio_values1_annual <- portfolio_values1 %>% mutate(Return = Return * 252) %>% mutate(Risk1 = Risk1 * sqrt(252), Risk2 = Risk2 * sqrt(252), Risk3 = Risk3 * sqrt(252), Risk4 = Risk4 * sqrt(252), Risk5 = Risk5 * sqrt(252)) %>% mutate(SharpeRatio1 = SharpeRatio1 * sqrt(252), SharpeRatio2 = SharpeRatio2 * sqrt(252), SharpeRatio3 = SharpeRatio3 * sqrt(252), SharpeRatio4 = SharpeRatio4 * sqrt(252), SharpeRatio5 = SharpeRatio5 * sqrt(252))
min_var1.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk1),]
min_var2.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk2),]
min_var3.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk3),]
min_var4.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk4),]
min_mad.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk5),]
max_sr1.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio1),]
max_sr2.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio2),]
max_sr3.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio3),]
max_sr4.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio4),]
max_sr5.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio5),]

rbind(min_var1.a, min_var2.a, min_var3.a, min_var4.a, min_mad.a, max_sr1.a, max_sr2.a, max_sr3.a, max_sr4.a, max_sr5.a)
## # A tibble: 10 × 16
##         KO    PEP     PG      V   WMT  Return Risk1  Risk2  Risk3  Risk4  Risk5
##      <dbl>  <dbl>  <dbl>  <dbl> <dbl>   <dbl> <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
##  1 0.277   0.0105 0.149  0.276  0.287  0.0219 0.104 0.0438 0.0658 0.0277 0.0804
##  2 0.0326  0.0264 0.404  0.346  0.190  0.0547 0.110 0.0428 0.0697 0.0272 0.0847
##  3 0.206   0.0906 0.0983 0.287  0.319  0.0364 0.104 0.0435 0.0652 0.0272 0.0813
##  4 0.153   0.0331 0.0517 0.0474 0.715  0.0838 0.117 0.0440 0.0706 0.0266 0.0933
##  5 0.393   0.0138 0.106  0.264  0.223 -0.0123 0.105 0.0444 0.0673 0.0286 0.0800
##  6 0.00103 0.0178 0.0531 0.432  0.496  0.137  0.113 0.0452 0.0706 0.0282 0.0876
##  7 0.00103 0.0178 0.0531 0.432  0.496  0.137  0.113 0.0452 0.0706 0.0282 0.0876
##  8 0.00103 0.0178 0.0531 0.432  0.496  0.137  0.113 0.0452 0.0706 0.0282 0.0876
##  9 0.00103 0.0178 0.0531 0.432  0.496  0.137  0.113 0.0452 0.0706 0.0282 0.0876
## 10 0.00103 0.0178 0.0531 0.432  0.496  0.137  0.113 0.0452 0.0706 0.0282 0.0876
## # ℹ 5 more variables: SharpeRatio1 <dbl>, SharpeRatio2 <dbl>,
## #   SharpeRatio3 <dbl>, SharpeRatio4 <dbl>, SharpeRatio5 <dbl>
p1 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk1, y = Return, color = SharpeRatio1)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (SD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk1,
                 y = Return), data = min_var1.a, color = 'orange') +
  geom_point(aes(x = Risk1,
                 y = Return), data = max_sr1.a, color = 'orange4', shape = 18)
ggplotly(p1)
p2 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk2, y = Return, color = SharpeRatio2)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VEV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk2,
                 y = Return), data = min_var2.a, color = 'green') +
  geom_point(aes(x = Risk2,
                 y = Return), data = max_sr2.a, color = 'green4', shape = 18)
ggplotly(p2)
p3 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk3, y = Return, color = SharpeRatio3)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VES)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk3,
                 y = Return), data = min_var3.a, color = 'red') +
  geom_point(aes(x = Risk3,
                 y = Return), data = max_sr3.a, color = 'red4', shape = 18)
ggplotly(p3)
p4 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk4, y = Return, color = SharpeRatio4)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VESV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk4,
                 y = Return), data = min_var4.a, color = 'purple') +
  geom_point(aes(x = Risk4,
                 y = Return), data = max_sr4.a, color = 'purple4', shape = 18)
ggplotly(p4)
p5 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk5, y = Return, color = SharpeRatio5)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (MAD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk5,
                 y = Return), data = min_mad.a, color = 'blue') +
  geom_point(aes(x = Risk5,
                 y = Return), data = max_sr5.a, color = 'blue4', shape = 18)
ggplotly(p5)

Plots cummulative returns of the test sample

MVP1 <- as.matrix(test)%*%as.vector(as.numeric(min_var1[1:nasset]))
MVP2 <- as.matrix(test)%*%as.vector(as.numeric(min_var2[1:nasset]))
MVP3 <- as.matrix(test)%*%as.vector(as.numeric(min_var3[1:nasset]))
MVP4 <- as.matrix(test)%*%as.vector(as.numeric(min_var4[1:nasset]))
MVP5 <- as.matrix(test)%*%as.vector(as.numeric(min_mad[1:nasset]))
TP1<-as.matrix(test)%*%as.vector(as.numeric(max_sr1[1:nasset]))
TP2<-as.matrix(test)%*%as.vector(as.numeric(max_sr2[1:nasset]))
TP3<-as.matrix(test)%*%as.vector(as.numeric(max_sr3[1:nasset]))
TP4<-as.matrix(test)%*%as.vector(as.numeric(max_sr4[1:nasset]))
TP5<-as.matrix(test)%*%as.vector(as.numeric(max_sr5[1:nasset]))
EWQ<-as.matrix(test)%*%as.vector(rep(1/nasset, nasset))
assets <- c("MVP1", "MVP2", "MVP3", "MVP4", "MVP5", "TP1", "TP2", "TP3", "TP4", "TP5", "EWQ")

#Portfolios <- merge(test[, 1], cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))[, -c(1)]

Portfolios <- cbind.data.frame(cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))

colnames(Portfolios) <- assets
# Define start and end dates
start_date <- as.Date("2023-01-01")
end_date <- as.Date("2023-12-31")
# Create a sequence of dates
date_sequence <- seq(start_date, end_date, by = "day")
#date_sequence

# Number of last values to select
nTemp <- nrow(Portfolios)

# Select the last 'n' values from the vector
TestDates <- date_sequence[(length(date_sequence) - nTemp + 1):length(date_sequence)]
#TestDates
row.names(Portfolios) <- TestDates
dygraph(Portfolios, main = 'Cummulative Returns for Test Period')%>%
dySeries('MVP1', label = 'MVP', col = "orange") %>%
dySeries('MVP2', label = 'MRP2', col = "green") %>%
dySeries('MVP3', label = 'MRP3', col = "red") %>%  
dySeries('MVP4', label = 'MRP4', col = "purple") %>%
dySeries('MVP5', label = 'MRP5', col = "blue") %>%
dySeries('TP1', label = 'TP', col = "orange", drawPoints = TRUE) %>% 
dySeries('TP2', label = 'MRRP2', col = "green", drawPoints = TRUE) %>%
dySeries('TP3', label = 'MRRP3', col = "red", drawPoints = TRUE) %>%  
dySeries('TP4', label = 'MRRP4', col = "purple", drawPoints = TRUE) %>% 
dySeries('TP5', label = 'MRRP5', col = "blue", drawPoints = TRUE) %>%  
dySeries('EWQ', label = 'EWQ', col = "black") %>% 
dyRangeSelector(height = 30)%>%
  dyLegend(width = 500)

Choose cummulative return from volatility correlations - empcor network portfolio

CumReturnVolCorr_low_risk <- cumsum(TP2)
CumReturnVolCorr_low_risk
##  [1] -0.0053055695 -0.0083719343  0.0020949511  0.0015499428  0.0054289752
##  [6]  0.0105248882  0.0198071011  0.0224885830  0.0177341904  0.0082606698
## [11]  0.0011304122  0.0047802696  0.0183949006  0.0212260731  0.0076640758
## [16]  0.0009287753  0.0148712035  0.0201894924  0.0310381728  0.0423171308
## [21]  0.0398679142  0.0406386952  0.0451582424  0.0403276061  0.0351439385
## [26]  0.0489244885  0.0528171697  0.0566538060  0.0646733819  0.0258378671
## [31]  0.0246516748  0.0248969231  0.0305044775  0.0299215190  0.0355148381
## [36]  0.0373406994  0.0416521137  0.0352526634  0.0392798284  0.0343366506
## [41]  0.0306623738  0.0335771298  0.0275606799  0.0268333511  0.0208078580
## [46]  0.0238570872  0.0294856969  0.0443411202  0.0304733303  0.0307685804
## [51]  0.0396112613  0.0440073850  0.0323350574  0.0402084355  0.0447522951
## [56]  0.0455814427  0.0499674488  0.0513228882  0.0518375346

Portfolio selected from emperical_DBSCAN_2023_highest_mean

emperical_DBSCAN_2023_highest_mean <- read.csv("~/Desktop/PO/DBSCAN/EMP/2023/emperical_DBSCAN_2023_highest_mean.csv")

#remove the date column
asset_prices<-emperical_DBSCAN_2023_highest_mean[,-1]
# calculate returns
ret_tidy1 = apply(asset_prices,2, log)
head(ret_tidy1)
##       BTC.USD  ETH.USD     NVDA     TSLA   XRP.USD
## [1,] 9.721957 7.102317 2.660650 4.683057 -1.067625
## [2,] 9.732891 7.136107 2.690517 4.733036 -1.056145
## [3,] 9.731318 7.131250 2.657151 4.703566 -1.084594
## [4,] 9.738139 7.146283 2.697948 4.727919 -1.065240
## [5,] 9.752464 7.186552 2.748406 4.785573 -1.051710
## [6,] 9.766882 7.197874 2.766227 4.777862 -1.046283
ret_tidy2 = diff(ret_tidy1)
head(ret_tidy2)
##           BTC.USD      ETH.USD         NVDA         TSLA     XRP.USD
## [1,]  0.010934154  0.033789247  0.029867310  0.049978841  0.01148044
## [2,] -0.001572818 -0.004856888 -0.033366243 -0.029469077 -0.02844903
## [3,]  0.006820792  0.015033458  0.040796800  0.024352155  0.01935358
## [4,]  0.014325077  0.040269095  0.050458408  0.057654579  0.01353075
## [5,]  0.014418134  0.011321725  0.017820810 -0.007711028  0.00542694
## [6,]  0.027621150  0.037696756  0.005766143  0.036109205  0.06320558
ret_tidy = exp (ret_tidy2) - 1 #simple returns
#remove first row
asset_returns <- ret_tidy[-1,]

#no.of assets in the portfolio 
nasset<-ncol(asset_returns)

# testing and training data sets (each data set has 252 observations)
# Divide the data set in to 3:1 (75% training and 25% testing)
# testing period - January - September (189 data points)
# training period - October - December (62 data points)

n.total<-252
n.train<- 189

train = asset_returns[1:n.train,]
test = asset_returns[-(1:(n.train)),]
##summary statistics 
rhosign<-apply(as.matrix(train), MARGIN=2, FUN=rho.cal)
rhovol<-apply(as.matrix(train), MARGIN=2, FUN=rho.vol)
assetsummary<-data.frame(apply(train, 2, mean), apply(train, 2, sd), rhovol, rhosign, apply(train, 2, skewness),
                 apply(train, 2, kurtosis))
xtable(assetsummary, digits=4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:55 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrr}
##   \hline
##  & apply.train..2..mean. & apply.train..2..sd. & rhovol & rhosign & apply.train..2..skewness. & apply.train..2..kurtosis. \\ 
##   \hline
## BTC.USD & 0.0030 & 0.0299 & 0.8520 & 0.6790 & 1.7637 & 9.5856 \\ 
##   ETH.USD & 0.0018 & 0.0303 & 0.8551 & 0.7043 & 0.9948 & 5.3989 \\ 
##   NVDA & 0.0064 & 0.0329 & 0.8519 & 0.6880 & 2.4113 & 14.1147 \\ 
##   TSLA & 0.0050 & 0.0344 & 0.9346 & 0.7674 & 0.2517 & 0.7862 \\ 
##   XRP.USD & 0.0039 & 0.0659 & 0.9197 & 0.4595 & 7.3370 & 77.7697 \\ 
##    \hline
## \end{tabular}
## \end{table}
plot(train, legend.loc=1)
## Warning in plot.window(...): "legend.loc" is not a graphical parameter
## Warning in plot.xy(xy, type, ...): "legend.loc" is not a graphical parameter
## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter

## Warning in axis(side = side, at = at, labels = labels, ...): "legend.loc" is
## not a graphical parameter
## Warning in box(...): "legend.loc" is not a graphical parameter
## Warning in title(...): "legend.loc" is not a graphical parameter

Lets calculate annualized portfolio return, risk, and gamma from the simulated portfolio returns with portfolio weights. (simulated weights)

## portfolio return, sd and gamma
## w is the random weight
## data = train or test
portfolio_info = function(w, data){
  port.data <- data%*%as.vector(w)
  port.cdf <- ecdf(port.data)
  port.return <- mean (port.data)
  port.sd <- sd (port.data)
  port.signrho <- cor (port.data - port.return, sign(port.data - port.return))
# port.signrho3 <- cor (sign(port.data - port.return), (port.data - port.return)^3)
# port.skewrho <- cor (port.data - port.return, (port.data - port.return)^2)
  port.volcor <- cor (abs(port.data - port.return), (port.data - port.return)^2) #volatlity correlation
  port.skewness <- skewness (port.data) #mu_3/sigma^3
  port.kurtosis <- kurtosis (port.data) #excess kurtosis mu_4/sigma^4 - 3
  return(c(port.return, port.sd, port.volcor, port.signrho, port.cdf(port.return), port.skewness, port.kurtosis))
}
# In stat matrix and weight matrix nrow = no.of assets in the portfolio (need to change), ncol is fixed to 7 , for loop i in 1:nrow
stat<-matrix(0, nrow = nasset, ncol = 7)
weight<-matrix(0, nrow = nasset, ncol = nasset)
for (i in 1:nasset){
weight[i, ] <- get_weights(nasset)
stat[i, ] <- portfolio_info (weight[i, ], as.matrix(train))
}
xtable(weight, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:55 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.0109 & 0.4166 & 0.2862 & 0.0183 & 0.2679 \\ 
##   2 & 0.1121 & 0.2552 & 0.2350 & 0.2922 & 0.1055 \\ 
##   3 & 0.3109 & 0.0787 & 0.1749 & 0.3980 & 0.0375 \\ 
##   4 & 0.1970 & 0.2870 & 0.1406 & 0.1338 & 0.2416 \\ 
##   5 & 0.1658 & 0.1788 & 0.3624 & 0.1164 & 0.1765 \\ 
##    \hline
## \end{tabular}
## \end{table}
xtable(stat, digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:58:55 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 & 6 & 7 \\ 
##   \hline
## 1 & 0.0037 & 0.0297 & 0.8452 & 0.6595 & 0.5344 & 2.8054 & 20.2643 \\ 
##   2 & 0.0042 & 0.0240 & 0.8843 & 0.7662 & 0.5873 & 0.8316 & 2.1434 \\ 
##   3 & 0.0043 & 0.0235 & 0.9402 & 0.7816 & 0.5714 & 0.4152 & 0.3020 \\ 
##   4 & 0.0036 & 0.0285 & 0.8456 & 0.6773 & 0.5185 & 2.2712 & 14.9390 \\ 
##   5 & 0.0044 & 0.0255 & 0.8468 & 0.7234 & 0.5714 & 1.7175 & 8.2979 \\ 
##    \hline
## \end{tabular}
## \end{table}

Check for the portfolio sd can be calcualted by both the formula and sd of the simulated portfolio.

We have everything we need to perform our optimization. All we need now is to run this code on 8000 random portfolios. For that we will use a for loop.

Before we do that, we need to create empty vectors and matrix for storing our values.

#change nasset to no of assets in portfolio
num_port <- 10000
nasset <- nasset

# Creating a matrix to store the weights

all_wts1 <- matrix(nrow = num_port,
                  ncol = nasset)

# Creating an empty vector to store
# 8000 Portfolio returns

port_returns <- vector('numeric', length = num_port)

# Creating an empty vector to store
# 8000 Portfolio variances

port_risk.var1 <- vector('numeric', length = num_port)
port_risk.var2 <- vector('numeric', length = num_port)
port_risk.var3 <- vector('numeric', length = num_port)
port_risk.var4 <- vector('numeric', length = num_port)
port_risk.mad <- vector('numeric', length = num_port)

Sharpe_ratio.sd1 <- vector('numeric', length = num_port)
Sharpe_ratio.sd2 <- vector('numeric', length = num_port)
Sharpe_ratio.sd3 <- vector('numeric', length = num_port)
Sharpe_ratio.sd4 <- vector('numeric', length = num_port)
Sharpe_ratio.mad <- vector('numeric', length = num_port)

Next lets run the for loop 10000 times.

port.info <- matrix(0, nrow = 10000, ncol = 7)

ptm <- proc.time()

for (i in seq_along(port_returns)) {
  
  wts <- get_weights(nasset)
  
  # Storing weight in the matrix
  all_wts1[i,] <- wts
  
  # Portfolio returns
  
  port.info [i, ]<- portfolio_info (wts, as.matrix(train))
  
  # Storing Portfolio Returns values
  port_returns[i] <- port.info[i, 1]
  
  # Creating and storing portfolio risk
  port_risk.var1 [i] <- port.info[i, 2]
  port_risk.var2 [i] <- sqrt(1 - port.info[i, 3]^2)*port.info[i, 2]
  port_risk.var3 [i] <- sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.var4 [i] <- sqrt(1 - port.info[i, 3]^2)*sqrt(1 - port.info[i, 4]^2)*port.info[i, 2]
  port_risk.mad [i] <- 2*port.info[i, 2]*port.info[i, 4]*sqrt(port.info[i, 5]*(1-port.info[i, 5]))
  
  # Creating and storing Portfolio Sharpe Ratios
  # Assuming 0% Risk free rate
  
  Sharpe_ratio.sd1 [i] <- port_returns[i]/port_risk.var1 [i]
  Sharpe_ratio.sd2 [i] <- port_returns[i]/port_risk.var2 [i]
  Sharpe_ratio.sd3 [i] <- port_returns[i]/port_risk.var3 [i]
  Sharpe_ratio.sd4 [i] <- port_returns[i]/port_risk.var4 [i]
  Sharpe_ratio.mad [i] <- port_returns[i]/port_risk.mad [i]
}
proc.time()-ptm
##    user  system elapsed 
##  10.757   0.132  16.159
port.info.data <- as.data.frame(port.info)

ggplot(port.info.data, aes(x=V6, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Skewness") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V7, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Kurtosis") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V2, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V3, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Volatlity Correlation") + ylab ("Volatlity")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V2)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Volatility")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V6)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Skewness")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V7)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Kurtosis")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

ggplot(port.info.data, aes(x=V4, y=V1)) + geom_point(color="blue", alpha=0.5) +geom_smooth(color="darkred") + xlab ("Sign Correlation") + ylab ("Return")
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

We now create a data table to store all the values together (using sd).

# Storing the values in the table (5 columns and 8000 rows)
portfolio_values1 <- tibble(Return = port_returns,
                  Risk1 = port_risk.var1,
                  Risk2 = port_risk.var2,
                  Risk3 = port_risk.var3,
                  Risk4 = port_risk.var4,
                  Risk5 = port_risk.mad,
                  SharpeRatio1 = Sharpe_ratio.sd1,
                  SharpeRatio2 = Sharpe_ratio.sd2,
                  SharpeRatio3 = Sharpe_ratio.sd3,
                  SharpeRatio4 = Sharpe_ratio.sd4,
                  SharpeRatio5 = Sharpe_ratio.mad,
                  )
# Converting matrix to a tibble and changing column names
all_wts1 <- tk_tbl(all_wts1)
## Warning in tk_tbl.data.frame(as.data.frame(data), preserve_index, rename_index,
## : Warning: No index to preserve. Object otherwise converted to tibble
## successfully.
colnames(all_wts1) <- colnames(asset_returns)

# Combing all the values together
portfolio_values1 <- tk_tbl(cbind(all_wts1, portfolio_values1))
## Warning in tk_tbl.data.frame(cbind(all_wts1, portfolio_values1)): Warning: No
## index to preserve. Object otherwise converted to tibble successfully.

We have the weights in each asset with the risk and returns along with the Sharpe ratio of each portfolio. We use daily data to determine the portfolios.

Next lets look at the portfolios that matter the most.

min_var1 <- portfolio_values1[which.min(portfolio_values1$Risk1),]
min_var2 <- portfolio_values1[which.min(portfolio_values1$Risk2),]
min_var3 <- portfolio_values1[which.min(portfolio_values1$Risk3),]
min_var4 <- portfolio_values1[which.min(portfolio_values1$Risk4),]
min_mad <- portfolio_values1[which.min(portfolio_values1$Risk5),]
max_sr1 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio1),]
max_sr2 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio2),]
max_sr3 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio3),]
max_sr4 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio4),]
max_sr5 <- portfolio_values1[which.max(portfolio_values1$SharpeRatio5),]
rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5)
## # A tibble: 10 × 16
##    BTC.USD ETH.USD  NVDA  TSLA XRP.USD  Return  Risk1   Risk2  Risk3   Risk4
##      <dbl>   <dbl> <dbl> <dbl>   <dbl>   <dbl>  <dbl>   <dbl>  <dbl>   <dbl>
##  1 0.312   0.144   0.335 0.206 0.00255 0.00437 0.0225 0.00925 0.0141 0.00582
##  2 0.0682  0.212   0.237 0.452 0.0308  0.00446 0.0242 0.00721 0.0149 0.00443
##  3 0.198   0.221   0.288 0.291 0.00226 0.00428 0.0226 0.00836 0.0138 0.00511
##  4 0.0682  0.212   0.237 0.452 0.0308  0.00446 0.0242 0.00721 0.0149 0.00443
##  5 0.417   0.150   0.286 0.132 0.0141  0.00406 0.0228 0.0108  0.0151 0.00712
##  6 0.258   0.00198 0.437 0.285 0.0174  0.00506 0.0237 0.0105  0.0151 0.00667
##  7 0.255   0.0110  0.260 0.449 0.0247  0.00478 0.0242 0.00741 0.0149 0.00457
##  8 0.258   0.00198 0.437 0.285 0.0174  0.00506 0.0237 0.0105  0.0151 0.00667
##  9 0.255   0.0110  0.260 0.449 0.0247  0.00478 0.0242 0.00741 0.0149 0.00457
## 10 0.00577 0.0198  0.684 0.211 0.0791  0.00578 0.0280 0.0145  0.0194 0.0100 
## # ℹ 6 more variables: Risk5 <dbl>, SharpeRatio1 <dbl>, SharpeRatio2 <dbl>,
## #   SharpeRatio3 <dbl>, SharpeRatio4 <dbl>, SharpeRatio5 <dbl>
xtable(rbind(min_var1, min_var2, min_var3, min_var4, min_mad, max_sr1, max_sr2, max_sr3, max_sr4, max_sr5), digits = 6)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:59:37 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrrrrrrrrrrrrr}
##   \hline
##  & BTC.USD & ETH.USD & NVDA & TSLA & XRP.USD & Return & Risk1 & Risk2 & Risk3 & Risk4 & Risk5 & SharpeRatio1 & SharpeRatio2 & SharpeRatio3 & SharpeRatio4 & SharpeRatio5 \\ 
##   \hline
## 1 & 0.312010 & 0.144384 & 0.334762 & 0.206293 & 0.002550 & 0.004369 & 0.022454 & 0.009245 & 0.014126 & 0.005816 & 0.017217 & 0.194596 & 0.472618 & 0.309312 & 0.751232 & 0.253783 \\ 
##   2 & 0.068238 & 0.212033 & 0.237307 & 0.451625 & 0.030797 & 0.004463 & 0.024156 & 0.007211 & 0.014855 & 0.004434 & 0.018853 & 0.184738 & 0.618873 & 0.300400 & 1.006344 & 0.236703 \\ 
##   3 & 0.197740 & 0.220899 & 0.288106 & 0.291000 & 0.002255 & 0.004283 & 0.022596 & 0.008364 & 0.013797 & 0.005107 & 0.017509 & 0.189548 & 0.512038 & 0.310421 & 0.838563 & 0.244614 \\ 
##   4 & 0.068238 & 0.212033 & 0.237307 & 0.451625 & 0.030797 & 0.004463 & 0.024156 & 0.007211 & 0.014855 & 0.004434 & 0.018853 & 0.184738 & 0.618873 & 0.300400 & 1.006344 & 0.236703 \\ 
##   5 & 0.417239 & 0.150318 & 0.286276 & 0.132083 & 0.014083 & 0.004061 & 0.022806 & 0.010758 & 0.015085 & 0.007116 & 0.017063 & 0.178082 & 0.377511 & 0.269226 & 0.570724 & 0.238012 \\ 
##   6 & 0.258299 & 0.001980 & 0.437053 & 0.285256 & 0.017412 & 0.005061 & 0.023725 & 0.010517 & 0.015053 & 0.006673 & 0.018176 & 0.213331 & 0.481256 & 0.336227 & 0.758497 & 0.278449 \\ 
##   7 & 0.255241 & 0.011034 & 0.259594 & 0.449421 & 0.024710 & 0.004778 & 0.024158 & 0.007412 & 0.014879 & 0.004565 & 0.018865 & 0.197769 & 0.644599 & 0.321103 & 1.046589 & 0.253259 \\ 
##   8 & 0.258299 & 0.001980 & 0.437053 & 0.285256 & 0.017412 & 0.005061 & 0.023725 & 0.010517 & 0.015053 & 0.006673 & 0.018176 & 0.213331 & 0.481256 & 0.336227 & 0.758497 & 0.278449 \\ 
##   9 & 0.255241 & 0.011034 & 0.259594 & 0.449421 & 0.024710 & 0.004778 & 0.024158 & 0.007412 & 0.014879 & 0.004565 & 0.018865 & 0.197769 & 0.644599 & 0.321103 & 1.046589 & 0.253259 \\ 
##   10 & 0.005774 & 0.019797 & 0.683964 & 0.211395 & 0.079070 & 0.005784 & 0.028000 & 0.014457 & 0.019365 & 0.009998 & 0.020074 & 0.206579 & 0.400113 & 0.298699 & 0.578537 & 0.288148 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change min_var1[1:nassets] and all the indexes after that accordingly
p1 <- cbind(min_var1[1:nasset], 252*min_var1[nasset+1], sqrt(252)*min_var1[nasset+2], sqrt(252)*min_var1[nasset+7])
p2 <- cbind(min_var2[1:nasset], 252*min_var2[nasset+1], sqrt(252)*min_var2[nasset+3], sqrt(252)*min_var2[nasset+8])
p3 <- cbind(min_var3[1:nasset], 252*min_var3[nasset+1], sqrt(252)*min_var3[nasset+4], sqrt(252)*min_var3[nasset+9])
p4 <- cbind(min_var4[1:nasset], 252*min_var4[nasset+1], sqrt(252)*min_var4[nasset+5], sqrt(252)*min_var4[nasset+10])
p5 <- cbind(min_mad[1:nasset], 252*min_mad[nasset+1], sqrt(252)*min_mad[nasset+6], sqrt(252)*min_mad[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:59:37 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.31201 & 0.06824 & 0.19774 & 0.06824 & 0.41724 \\ 
##   2 & 0.14438 & 0.21203 & 0.22090 & 0.21203 & 0.15032 \\ 
##   3 & 0.33476 & 0.23731 & 0.28811 & 0.23731 & 0.28628 \\ 
##   4 & 0.20629 & 0.45162 & 0.29100 & 0.45162 & 0.13208 \\ 
##   5 & 0.00255 & 0.03080 & 0.00226 & 0.03080 & 0.01408 \\ 
##   6 & 1.10109 & 1.12457 & 1.07930 & 1.12457 & 1.02345 \\ 
##   7 & 0.35644 & 0.11447 & 0.21902 & 0.07039 & 0.27087 \\ 
##   8 & 3.08911 & 9.82431 & 4.92779 & 15.97522 & 3.77832 \\ 
##    \hline
## \end{tabular}
## \end{table}
# change max_sr[1:nassets] and all the indexes after that accordingly
p1 <- cbind(max_sr1[1:nasset], 252*max_sr1[nasset+1], sqrt(252)*max_sr1[nasset+2], sqrt(252)*max_sr1[nasset+7])
p2 <- cbind(max_sr2[1:nasset], 252*max_sr2[nasset+1], sqrt(252)*max_sr2[nasset+3], sqrt(252)*max_sr2[nasset+8])
p3 <- cbind(max_sr3[1:nasset], 252*max_sr3[nasset+1], sqrt(252)*max_sr3[nasset+4], sqrt(252)*max_sr3[nasset+9])
p4 <- cbind(max_sr4[1:nasset], 252*max_sr4[nasset+1], sqrt(252)*max_sr4[nasset+5], sqrt(252)*max_sr4[nasset+10])
p5 <- cbind(max_sr5[1:nasset], 252*max_sr5[nasset+1], sqrt(252)*max_sr5[nasset+6], sqrt(252)*max_sr5[nasset+11])
xtable(t(rbind(as.numeric(p1), as.numeric(p2), as.numeric(p3), as.numeric(p4), as.numeric(p5))), digits = 5)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:59:37 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rrrrrr}
##   \hline
##  & 1 & 2 & 3 & 4 & 5 \\ 
##   \hline
## 1 & 0.25830 & 0.25524 & 0.25830 & 0.25524 & 0.00577 \\ 
##   2 & 0.00198 & 0.01103 & 0.00198 & 0.01103 & 0.01980 \\ 
##   3 & 0.43705 & 0.25959 & 0.43705 & 0.25959 & 0.68396 \\ 
##   4 & 0.28526 & 0.44942 & 0.28526 & 0.44942 & 0.21140 \\ 
##   5 & 0.01741 & 0.02471 & 0.01741 & 0.02471 & 0.07907 \\ 
##   6 & 1.27543 & 1.20398 & 1.27543 & 1.20398 & 1.45763 \\ 
##   7 & 0.37662 & 0.11766 & 0.23896 & 0.07247 & 0.31866 \\ 
##   8 & 3.38653 & 10.23270 & 5.33744 & 16.61408 & 4.57421 \\ 
##    \hline
## \end{tabular}
## \end{table}
nasset <- ncol(asset_returns)
w1 <- min_var1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w2 <- min_var2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w3 <- min_var3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w4 <- min_var4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w5 <- min_mad[, 1:nasset] %>% gather () %>% arrange(desc(value))
w6 <- max_sr1[, 1:nasset] %>% gather () %>% arrange(desc(value))
w7 <- max_sr2[, 1:nasset] %>% gather () %>% arrange(desc(value))
w8 <- max_sr3[, 1:nasset] %>% gather () %>% arrange(desc(value))
w9 <- max_sr4[, 1:nasset] %>% gather () %>% arrange(desc(value))
w10 <- max_sr5[, 1:nasset] %>% gather () %>% arrange(desc(value))

xtable(cbind(head (w1, 10), head (w2, 10), head (w3, 10), head (w4, 10), head (w5, 10), head (w6, 10), head (w7, 10), head (w8, 10), head (w9, 10), head (w10, 10)), digits = 4)
## % latex table generated in R 4.3.1 by xtable 1.8-4 package
## % Tue Sep 24 15:59:38 2024
## \begin{table}[ht]
## \centering
## \begin{tabular}{rlrlrlrlrlrlrlrlrlrlr}
##   \hline
##  & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value & key & value \\ 
##   \hline
## 1 & NVDA & 0.3348 & TSLA & 0.4516 & TSLA & 0.2910 & TSLA & 0.4516 & BTC.USD & 0.4172 & NVDA & 0.4371 & TSLA & 0.4494 & NVDA & 0.4371 & TSLA & 0.4494 & NVDA & 0.6840 \\ 
##   2 & BTC.USD & 0.3120 & NVDA & 0.2373 & NVDA & 0.2881 & NVDA & 0.2373 & NVDA & 0.2863 & TSLA & 0.2853 & NVDA & 0.2596 & TSLA & 0.2853 & NVDA & 0.2596 & TSLA & 0.2114 \\ 
##   3 & TSLA & 0.2063 & ETH.USD & 0.2120 & ETH.USD & 0.2209 & ETH.USD & 0.2120 & ETH.USD & 0.1503 & BTC.USD & 0.2583 & BTC.USD & 0.2552 & BTC.USD & 0.2583 & BTC.USD & 0.2552 & XRP.USD & 0.0791 \\ 
##   4 & ETH.USD & 0.1444 & BTC.USD & 0.0682 & BTC.USD & 0.1977 & BTC.USD & 0.0682 & TSLA & 0.1321 & XRP.USD & 0.0174 & XRP.USD & 0.0247 & XRP.USD & 0.0174 & XRP.USD & 0.0247 & ETH.USD & 0.0198 \\ 
##   5 & XRP.USD & 0.0026 & XRP.USD & 0.0308 & XRP.USD & 0.0023 & XRP.USD & 0.0308 & XRP.USD & 0.0141 & ETH.USD & 0.0020 & ETH.USD & 0.0110 & ETH.USD & 0.0020 & ETH.USD & 0.0110 & BTC.USD & 0.0058 \\ 
##    \hline
## \end{tabular}
## \end{table}

Lets plot the weights of each portfolio. First with the minimum variance portfolio.

p1 <- min_var4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset,Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Minimum Risk Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p1)
p2 <- max_sr4 %>%
  gather(colnames(asset_returns)[1]:colnames(asset_returns)[nasset], key = Asset,
         value = Weights) %>%
  mutate(Asset = as.factor(Asset)) %>%
  ggplot(aes(x = fct_reorder(Asset, Weights), y = Weights, fill = Asset)) +
  geom_bar(stat = 'identity') +
  theme_minimal() +
  labs(x = 'Assets', y = 'Weights', title = "Tangency Portfolio Weights") +
  scale_y_continuous(labels = scales::percent) 
ggplotly(p2)
#convert daily return, risk, SR to annualized ones

portfolio_values1_annual <- portfolio_values1 %>% mutate(Return = Return * 252) %>% mutate(Risk1 = Risk1 * sqrt(252), Risk2 = Risk2 * sqrt(252), Risk3 = Risk3 * sqrt(252), Risk4 = Risk4 * sqrt(252), Risk5 = Risk5 * sqrt(252)) %>% mutate(SharpeRatio1 = SharpeRatio1 * sqrt(252), SharpeRatio2 = SharpeRatio2 * sqrt(252), SharpeRatio3 = SharpeRatio3 * sqrt(252), SharpeRatio4 = SharpeRatio4 * sqrt(252), SharpeRatio5 = SharpeRatio5 * sqrt(252))
min_var1.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk1),]
min_var2.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk2),]
min_var3.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk3),]
min_var4.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk4),]
min_mad.a <- portfolio_values1_annual[which.min(portfolio_values1_annual$Risk5),]
max_sr1.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio1),]
max_sr2.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio2),]
max_sr3.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio3),]
max_sr4.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio4),]
max_sr5.a <- portfolio_values1_annual[which.max(portfolio_values1_annual$SharpeRatio5),]

rbind(min_var1.a, min_var2.a, min_var3.a, min_var4.a, min_mad.a, max_sr1.a, max_sr2.a, max_sr3.a, max_sr4.a, max_sr5.a)
## # A tibble: 10 × 16
##    BTC.USD ETH.USD  NVDA  TSLA XRP.USD Return Risk1 Risk2 Risk3  Risk4 Risk5
##      <dbl>   <dbl> <dbl> <dbl>   <dbl>  <dbl> <dbl> <dbl> <dbl>  <dbl> <dbl>
##  1 0.312   0.144   0.335 0.206 0.00255   1.10 0.356 0.147 0.224 0.0923 0.273
##  2 0.0682  0.212   0.237 0.452 0.0308    1.12 0.383 0.114 0.236 0.0704 0.299
##  3 0.198   0.221   0.288 0.291 0.00226   1.08 0.359 0.133 0.219 0.0811 0.278
##  4 0.0682  0.212   0.237 0.452 0.0308    1.12 0.383 0.114 0.236 0.0704 0.299
##  5 0.417   0.150   0.286 0.132 0.0141    1.02 0.362 0.171 0.239 0.113  0.271
##  6 0.258   0.00198 0.437 0.285 0.0174    1.28 0.377 0.167 0.239 0.106  0.289
##  7 0.255   0.0110  0.260 0.449 0.0247    1.20 0.383 0.118 0.236 0.0725 0.299
##  8 0.258   0.00198 0.437 0.285 0.0174    1.28 0.377 0.167 0.239 0.106  0.289
##  9 0.255   0.0110  0.260 0.449 0.0247    1.20 0.383 0.118 0.236 0.0725 0.299
## 10 0.00577 0.0198  0.684 0.211 0.0791    1.46 0.444 0.229 0.307 0.159  0.319
## # ℹ 5 more variables: SharpeRatio1 <dbl>, SharpeRatio2 <dbl>,
## #   SharpeRatio3 <dbl>, SharpeRatio4 <dbl>, SharpeRatio5 <dbl>
p1 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk1, y = Return, color = SharpeRatio1)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (SD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk1,
                 y = Return), data = min_var1.a, color = 'orange') +
  geom_point(aes(x = Risk1,
                 y = Return), data = max_sr1.a, color = 'orange4', shape = 18)
ggplotly(p1)
p2 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk2, y = Return, color = SharpeRatio2)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VEV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk2,
                 y = Return), data = min_var2.a, color = 'green') +
  geom_point(aes(x = Risk2,
                 y = Return), data = max_sr2.a, color = 'green4', shape = 18)
ggplotly(p2)
p3 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk3, y = Return, color = SharpeRatio3)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VES)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk3,
                 y = Return), data = min_var3.a, color = 'red') +
  geom_point(aes(x = Risk3,
                 y = Return), data = max_sr3.a, color = 'red4', shape = 18)
ggplotly(p3)
p4 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk4, y = Return, color = SharpeRatio4)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (VESV)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk4,
                 y = Return), data = min_var4.a, color = 'purple') +
  geom_point(aes(x = Risk4,
                 y = Return), data = max_sr4.a, color = 'purple4', shape = 18)
ggplotly(p4)
p5 <- portfolio_values1_annual %>%
  ggplot(aes(x = Risk5, y = Return, color = SharpeRatio5)) +
  geom_point(alpha = 0.4)+
  theme_classic() +
  scale_y_continuous(labels = scales::percent) +
  scale_x_continuous(labels = scales::percent) +
  labs(x = 'Annualized Risk (MAD)',
       y = 'Annualized Returns',
       title = "Portfolio Optimization & Efficient Frontier") +
  geom_point(aes(x = Risk5,
                 y = Return), data = min_mad.a, color = 'blue') +
  geom_point(aes(x = Risk5,
                 y = Return), data = max_sr5.a, color = 'blue4', shape = 18)
ggplotly(p5)

Plots cummulative returns of the test sample

MVP1 <- as.matrix(test)%*%as.vector(as.numeric(min_var1[1:nasset]))
MVP2 <- as.matrix(test)%*%as.vector(as.numeric(min_var2[1:nasset]))
MVP3 <- as.matrix(test)%*%as.vector(as.numeric(min_var3[1:nasset]))
MVP4 <- as.matrix(test)%*%as.vector(as.numeric(min_var4[1:nasset]))
MVP5 <- as.matrix(test)%*%as.vector(as.numeric(min_mad[1:nasset]))
TP1<-as.matrix(test)%*%as.vector(as.numeric(max_sr1[1:nasset]))
TP2<-as.matrix(test)%*%as.vector(as.numeric(max_sr2[1:nasset]))
TP3<-as.matrix(test)%*%as.vector(as.numeric(max_sr3[1:nasset]))
TP4<-as.matrix(test)%*%as.vector(as.numeric(max_sr4[1:nasset]))
TP5<-as.matrix(test)%*%as.vector(as.numeric(max_sr5[1:nasset]))
EWQ<-as.matrix(test)%*%as.vector(rep(1/nasset, nasset))
assets <- c("MVP1", "MVP2", "MVP3", "MVP4", "MVP5", "TP1", "TP2", "TP3", "TP4", "TP5", "EWQ")

#Portfolios <- merge(test[, 1], cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))[, -c(1)]

Portfolios <- cbind.data.frame(cumsum(MVP1), cumsum(MVP2), cumsum(MVP3), cumsum(MVP4), cumsum(MVP5), cumsum(TP1), cumsum(TP2), cumsum(TP3), cumsum(TP4), cumsum(TP5), cumsum(EWQ))

colnames(Portfolios) <- assets
# Define start and end dates
start_date <- as.Date("2023-01-01")
end_date <- as.Date("2023-12-31")
# Create a sequence of dates
date_sequence <- seq(start_date, end_date, by = "day")
#date_sequence

# Number of last values to select
nTemp <- nrow(Portfolios)

# Select the last 'n' values from the vector
TestDates <- date_sequence[(length(date_sequence) - nTemp + 1):length(date_sequence)]
#TestDates
row.names(Portfolios) <- TestDates
dygraph(Portfolios, main = 'Cummulative Returns for Test Period')%>%
dySeries('MVP1', label = 'MVP', col = "orange") %>%
dySeries('MVP2', label = 'MRP2', col = "green") %>%
dySeries('MVP3', label = 'MRP3', col = "red") %>%  
dySeries('MVP4', label = 'MRP4', col = "purple") %>%
dySeries('MVP5', label = 'MRP5', col = "blue") %>%
dySeries('TP1', label = 'TP', col = "orange", drawPoints = TRUE) %>% 
dySeries('TP2', label = 'MRRP2', col = "green", drawPoints = TRUE) %>%
dySeries('TP3', label = 'MRRP3', col = "red", drawPoints = TRUE) %>%  
dySeries('TP4', label = 'MRRP4', col = "purple", drawPoints = TRUE) %>% 
dySeries('TP5', label = 'MRRP5', col = "blue", drawPoints = TRUE) %>%  
dySeries('EWQ', label = 'EWQ', col = "black") %>% 
dyRangeSelector(height = 30)%>%
  dyLegend(width = 500)

Choose cummulative return from volatility correlations - highest mean

CumReturnVolCorr_high_mean <- cumsum(TP2)
CumReturnVolCorr_high_mean
##  [1]  0.012377821  0.003284629  0.010979811  0.010357839  0.002501144
##  [6] -0.017927621  0.007418199 -0.004565332 -0.037285488 -0.074504590
## [11] -0.086860738 -0.044861664 -0.024361347 -0.039670018 -0.065319267
## [16] -0.063164953 -0.074345503 -0.066650567 -0.039797435 -0.008470821
## [21]  0.002416071  0.012086994  0.021094431  0.026041380  0.011633235
## [26]  0.033129606  0.048365134  0.072724223  0.097053435  0.069490909
## [31]  0.073086633  0.087877646  0.083067969  0.077259741  0.077086069
## [36]  0.076677276  0.099036270  0.096065262  0.080222481  0.084913515
## [41]  0.094832356  0.119795941  0.113587851  0.124065138  0.137648221
## [46]  0.105826999  0.107582842  0.123774466  0.148496734  0.148165431
## [51]  0.156044766  0.160161264  0.143685055  0.163532658  0.160460395
## [56]  0.160948378  0.176895810  0.158320809  0.146142063

Merge and create a new dataframe for Without and With clustering

# Example data
CumReturnVolCorr <- data.frame(
  Date = as.character(TestDates),
  low_avg_risk = CumReturnVolCorr_low_avg_risk,
  low_risk = CumReturnVolCorr_low_risk,
  high_mean = CumReturnVolCorr_high_mean
)

Plot

library(ggplot2)

# Create the plot with date interval
ggplot(data = CumReturnVolCorr, aes(x = as.Date(Date))) +
  geom_line(aes(y = low_avg_risk, color = "low_avg_risk"), lwd = 1.5) +
  geom_line(aes(y = low_risk, color = "low_risk"), lwd = 1.5) +
  geom_line(aes(y = high_mean, color = "high_mean"), lwd = 1.5) + 
  labs(y = "Cumulative Return",
       x = "Date") +
  scale_color_manual(name = "Data",
                     values = c("low_avg_risk" = "blue", 
                                "low_risk" = "red", 
                                "high_mean" = "green"), # Add color for the new series
                     labels = c("low_avg_risk" = "lowest average risk", 
                                "low_risk" = "lowest risk", 
                                "high_mean" = "highest mean")) + # Adjust labels
  scale_x_date(date_breaks = "1 month", date_labels = "%Y-%m") + # Show dates at monthly intervals
  theme_minimal()